Skip to content
19 changes: 19 additions & 0 deletions contracts/Tracing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ contract TracingCaller {
this.start(counter - 1);
}

function destruct() external {
address recipient = msg.sender;
assembly {
selfdestruct(recipient)
}
}

function create_and_destruct() public {
TracingCallee newCallee = new TracingCallee();
newCallee.destruct();
}

function create() external returns (address) {
TracingCallee newCallee = new TracingCallee();
return address(newCallee);
Expand All @@ -52,6 +64,13 @@ contract TracingCallee {
emit CalleeCalled(counter);
}

function destruct() external {
address recipient = msg.sender;
assembly {
selfdestruct(recipient)
}
}

function failingFunction() external payable {
require(false, "This function always fails");
}
Expand Down
8 changes: 4 additions & 4 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@
"imports": {
"@std/cli": "jsr:@std/cli@^1.0.23",
"@std/encoding": "jsr:@std/encoding@^1.0.10",
"viem": "npm:viem@^2.38.3",
"viem/": "npm:/viem@^2.38.3/",
"viem": "npm:viem@^2.39.0",
"viem/": "npm:/viem@^2.39.0/",
"solc": "npm:solc@^0.8.30",
"@parity/resolc": "npm:@parity/resolc@^0.4.1",
"@parity/resolc": "npm:@parity/resolc@^0.5.0",
"@std/assert": "jsr:@std/assert@^1.0.15",
"@std/expect": "jsr:@std/expect@^1.0.17",
"@std/testing": "jsr:@std/testing@^1.0.16",
"@std/path": "jsr:@std/path@^1.1.2",
"@std/log": "jsr:@std/log@^0.224"
"@std/log": "jsr:@std/log@^0.224.14"
},
"compilerOptions": {
"strict": true
Expand Down
30 changes: 15 additions & 15 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

121 changes: 121 additions & 0 deletions src/__snapshots__/all-tests.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,73 @@ snapshot[`call-trace debug_traceCall 1`] = `
}
`;

snapshot[`call-trace selfdestruct 1`] = `
{
calls: [
{
from: "<contract_addr>",
gas: "<gas>",
gasUsed: "<gas>",
input: "0x",
to: "0x0000000000000000000000000000000000000000",
type: "SELFDESTRUCT",
value: "<selfdestruct_value>",
},
],
from: "0x0000000000000000000000000000000000000000",
gas: "<gas>",
gasUsed: "<gas>",
input: "0x2b68b9c6",
to: "<contract_addr>",
type: "CALL",
value: "0x0",
}
`;

snapshot[`call-trace create_and_destruct 1`] = `
{
calls: [
{
from: "<contract_addr>",
gas: "<gas>",
gasUsed: "<gas>",
input: "<tracing_callee_init_code>",
output: "<tracing_callee_runtime_code>",
to: "<addr>",
type: "CREATE",
value: "0x0",
},
{
calls: [
{
from: "<addr>",
gas: "<gas>",
gasUsed: "<gas>",
input: "0x",
to: "<contract_addr>",
type: "SELFDESTRUCT",
value: "<selfdestruct_value>",
},
],
from: "<contract_addr>",
gas: "<gas>",
gasUsed: "<gas>",
input: "0x2b68b9c6",
to: "<addr>",
type: "CALL",
value: "0x0",
},
],
from: "0x0000000000000000000000000000000000000000",
gas: "<gas>",
gasUsed: "<gas>",
input: "0xfadbb018",
to: "<contract_addr>",
type: "CALL",
value: "0x0",
}
`;

snapshot[`prestate deploy_contract.diff 1`] = `
{
post: {
Expand Down Expand Up @@ -1050,3 +1117,57 @@ snapshot[`prestate trace_tx_write_storage_twice.no_diff 1`] = `
},
}
`;

snapshot[`prestate selfdestruct.diff 1`] = `
{
post: {
"<tracing_contract_addr>": {
balance: "<balance>",
},
},
pre: {
"<tracing_contract_addr>": {
balance: "<balance>",
code: "<code>",
nonce: "<nonce>",
},
},
}
`;

snapshot[`prestate selfdestruct.no_diff 1`] = `
{
"<tracing_contract_addr>": {
balance: "<balance>",
code: "<code>",
nonce: "<nonce>",
},
}
`;

snapshot[`prestate create_and_destruct.diff 1`] = `
{
post: {
"<tracing_contract_addr>": {
nonce: "<nonce>",
},
},
pre: {
"<tracing_contract_addr>": {
balance: "<balance>",
code: "<code>",
nonce: "<nonce>",
},
},
}
`;

snapshot[`prestate create_and_destruct.no_diff 1`] = `
{
"<tracing_contract_addr>": {
balance: "<balance>",
code: "<code>",
nonce: "<nonce>",
},
}
`;
8 changes: 8 additions & 0 deletions src/test-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ export async function setupTests() {
]

await killProcessOnPort(8545)

const versionOutput = await new Deno.Command(geth, {
args: ['version'],
stdout: 'piped',
stderr: 'piped',
}).output()
const version = new TextDecoder().decode(versionOutput.stdout)
console.log(version)
console.log('🚀 Start geth...')
const gethProcess = new Deno.Command(geth, {
args: gethArgs,
Expand Down
40 changes: 40 additions & 0 deletions src/tracing-call-trace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,43 @@ Deno.test('call-trace debug_traceCall', opts, async (t) => {

await matchFixture(t, res)
})

Deno.test('call-trace selfdestruct', opts, async (t) => {
const tracingCallerAddr = await getTracingCallerAddr()
const res = await env.debugClient.traceCall(
{
to: tracingCallerAddr,
data: encodeFunctionData({
abi: TracingCallerAbi,
functionName: 'destruct',
args: [],
}),
},
'callTracer',
{ withLog: true },
)

await matchFixture(t, res)
})

Deno.test(
'call-trace create_and_destruct',
opts,
async (t) => {
const tracingCallerAddr = await getTracingCallerAddr()
const res = await env.debugClient.traceCall(
{
to: tracingCallerAddr,
data: encodeFunctionData({
abi: TracingCallerAbi,
functionName: 'create_and_destruct',
args: [],
}),
},
'callTracer',
{ withLog: true },
)

await matchFixture(t, res)
},
)
45 changes: 45 additions & 0 deletions src/tracing-prestate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
getPretraceFixtureReceipt,
getTracingCallerAddr,
} from './deploy_contracts.ts'
import { TracingCallerAbi } from '../codegen/abi/TracingCaller.ts'

const getBlock = memoized(async () => {
const receipt = await getPretraceFixtureReceipt()
Expand Down Expand Up @@ -445,3 +446,47 @@ Deno.test(
})
}),
)

Deno.test(
'prestate selfdestruct',
opts,
withDiffModes(async (t, config, diffMode) => {
const tracingCallerAddr = await getTracingCallerAddr()
const res = await env.debugClient.traceCall(
{
to: tracingCallerAddr,
data: encodeFunctionData({
abi: TracingCallerAbi,
functionName: 'destruct',
args: [],
}),
},
'prestateTracer',
config,
)
await matchFixture(t, res, diffMode)
}),
)

Deno.test(
'prestate create_and_destruct',
opts,
withDiffModes(
async (t, config, diffMode) => {
const tracingCallerAddr = await getTracingCallerAddr()
const res = await env.debugClient.traceCall(
{
to: tracingCallerAddr,
data: encodeFunctionData({
abi: TracingCallerAbi,
functionName: 'create_and_destruct',
args: [],
}),
},
'prestateTracer',
config,
)
await matchFixture(t, res, diffMode)
},
),
)