tracer: clarify prestateTracer diff mode behavior (#30912)

Based on
https://github.com/ethereum/go-ethereum/issues/30774#issuecomment-2504146053

Add more descrption for the `to` field in callTracer, and also refine
the `diffMode` in prestateTracer:
- Clarifies when ALL fields (`nonce`, `balance`, `code`) are included in
the `pre` object
- Adds detail about storage clearing behavior (zero value treatment)

---------

Signed-off-by: jsvisa <delweng@gmail.com>
Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com>
This commit is contained in:
Delweng 2024-12-16 22:48:43 +08:00 committed by GitHub
parent f8979f164c
commit 51b22135ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 61 additions and 56 deletions

View File

@ -59,43 +59,35 @@ Return:
```terminal
{
"gas":25523,
"failed":false,
"returnValue":"",
"structLogs":[
{
"pc":0,
"op":"PUSH1",
"gas":64580,
"gasCost":3,
"depth":1,
"error":null,
"stack":[
],
"memory":null,
"storage":{
}
},
{
"pc":2,
"op":"PUSH1",
"gas":64577,
"gasCost":3,
"depth":1,
"error":null,
"stack":[
"0000000000000000000000000000000000000000000000000000000000000060"
],
"memory":null,
"storage":{
}
},
...
"gas": 25523,
"failed": false,
"returnValue": "",
"structLogs": [
{
"pc": 0,
"op": "PUSH1",
"gas": 64580,
"gasCost": 3,
"depth": 1,
"error": null,
"stack": [ ... ],
"memory": null,
"storage": { ... }
},
{
"pc": 2,
"op": "PUSH1",
"gas": 64577,
"gasCost": 3,
"depth": 1,
"error": null,
"stack": [
"0000000000000000000000000000000000000000000000000000000000000060"
],
"memory": null,
"storage": { ... }
},
...
```
## Native tracers {#native-tracers}
@ -112,7 +104,7 @@ The `4byteTracer` collects the function selectors of every function executed in
Example call:
```sh
debug.traceTransaction( "0x214e597e35da083692f5386141e69f47e973b2c56e7a8073b1ea08fd7571e9de", {tracer: "4byteTracer"})
debug.traceTransaction("0x214e597e35da083692f5386141e69f47e973b2c56e7a8073b1ea08fd7571e9de", {tracer: "4byteTracer"})
```
Return:
@ -131,19 +123,26 @@ Return:
The `callTracer` tracks all the call frames executed during a transaction, including depth 0. The result will be a nested list of call frames, resembling how EVM works. They form a tree with the top-level call at root and sub-calls as children of the higher levels. Each call frame has the following fields:
| field | type | description |
| ------------ | ----------- | ------------------------------------ |
| type | string | CALL or CREATE |
| from | string | address |
| to | string | address |
| value | string | hex-encoded amount of value transfer |
| gas | string | hex-encoded gas provided for call |
| gasUsed | string | hex-encoded gas used during call |
| input | string | call data |
| output | string | return data |
| error | string | error, if any |
| revertReason | string | Solidity revert reason, if any |
| calls | []callframe | list of sub-calls |
| field | type | description |
| ------------ | ----------- | -------------------------------------------------------------------------------- |
| type | string | the type of call (CALL, STATICCALL, DELEGATECALL, CREATE, CREATE2, SELFDESTRUCT) |
| from | string | the address initiating the call |
| to | string | the target address receiving the call |
| value | string | hex-encoded amount of ETH transfer |
| gas | string | hex-encoded gas provided for call |
| gasUsed | string | hex-encoded gas used during call |
| input | string | call data |
| output | string | return data |
| error | string | error informaction if the call failed |
| revertReason | string | Solidity revert reason, if any |
| calls | []callframe | list of nested sub-calls |
Hints the `to` address, which varies by call type:
- `CALL/STATICCALL`: The contract or receiving address being called
- `DELEGATECALL`: The contract whose code is being executed
- `CREATE/CREATE2`: The address of the newly deployed contract
- `SELFDESTRUCT/SUICIDE`: The address of the refund recipient
Example Call:
@ -222,11 +221,17 @@ The prestate tracer has two modes: `prestate` and `diff`. The `prestate` mode re
In `diff` mode the result object will contain a `pre` and a `post` object:
1. The result only includes accounts that were modified. Accounts without changes will be omitted in this mode.
2. In `pre` you will find the state of an account before the tx started, and in `post` its state after tx execution finished.
3. `pre` can include fields that were not modified, if some other fields for the same account were modified.
4. `post` will contain only the modified fields. e.g. if `nonce` of an account hasn't changed it will be omitted from `post`.
5. Deletion (i.e. account selfdestruct, or storage clearing) will be signified by inclusion in `pre` and omission in `post`.
6. Insertion (i.e. account creation or new slots) will be signified by omission in `pre` and inclusion in `post`.
2. The `pre` object within the result captures the account's state at the beginning of the transaction, showcasing its initial values, while the `post` object represents the account's state once the transaction has been fully executed, revealing the outcome of the changes.
3. The accounts in the `pre` object will still contain all of their basic fields—nonce, balance, and code—even if those fields have not been modified. Storage slots, however, are an exception. Only non-empty slots that have been modified will be included. In other words, if a new slot was written to, it will not appear in the `pre` object.
4. The `post` object is more selective - it only contains the specific fields that were actually modified during the transaction. For example, if only the storage was modified, `post` will not include unchanged fields like `nonce`, `balance`, or `code`.
5. Deletion operations are represented by:
- Account selfdestruct: Account appears in `pre` but not in `post`
- Storage clearing (setting a storage value to zero is also treated as clearing): Storage slot appears in `pre` but not in `post`
6. Insertion operations are represented by:
- New account creation: Account appears in `post` but not in `pre`
- New storage slot: Storage slot appears in `post` but not in `pre`
To run this tracer in `diff` mode, pass `tracerConfig: {diffMode: true}` in the API call.