Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eth API: Trace installed bytecode in the Ethereum JSON-RPC trace_block output #11635

Open
Stebalien opened this issue Feb 20, 2024 · 3 comments

Comments

@Stebalien
Copy link
Member

The Ethereum JSON-RPC trace_block API currently returns 0xfe as the EVM bytecode for all newly created actors:

  1. For non-EVM actors, this makes sense as there's way to return any reasonable bytecode.
  2. For EVM actors, there's just no reliable way to get the bytecode because an EVM smart contract's bytecode can change multiple times over the course of the block, even without reverts, by invoking selfdestruct and re-deploying. Even EIP-6780 will maintain this behavior.

To fix this, we need some way to get the bytecode of an EVM smart contract in the middle of a block. We'll need to implement both:

Then, every time we see a "create" event in the trace, we can lookup the state of the smart contract after it finished running the constructor to retrieve the bytecode.

@aarshkshah1992
Copy link
Contributor

@rjan90 @jennijuju Why has this been prioritised ?

@Stebalien
Copy link
Member Author

An interim solution is to only handle smart contracts that live beyond the end of the block. Basically:

  1. While we process the trace, for each address (ID) at which a smart contract is deployed, record the last transaction that successfully (not reverted) created a smart contract there.
  2. After processing the trace, for each of those addresses, lookup the associated smart contract.
  3. If the smart contract has self-destructed and/or doesn't exist, ignore it.
  4. If the smart contract exists and is alive, get its bytecode and replace the "fake" bytecode we recorded in the trace with the real bytecode.

Note: we're only altering the trace of the last successful attempt to deploy a contract at any given address. Given that we won't have any intermediate and/or reverted state, that's all we can do. On the other hand, that's probably sufficient in most cases.

@Stebalien
Copy link
Member Author

Basically:

  1. If a call and/or sub-call hasn't been reverted, pass a non-nil deployedCode map with a type map[ActorID]*EthBytes through the tracing logic.
  2. When processing a contract creation and deployedCode is non-nil, record deployedCode[contractID] = &crateTraceAction.Code even if there's already an entry for contractID in this mapping.
  3. After processing the trace, for each contractID, codePtr in deployedCode, lookup the associated contract, assert that it isn't dead, and set *codePtr = contract.GetBytecode().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: ⌨️ In Progress
Status: 🖊 Planning
3 participants