Skip to content

[Bug] eth_createAccessList never traces the call and returns the input access list unchanged #1282

Description

@kriss39

Type

  • Bug
  • Feature
  • Proposal / Discussion

Summary

eth_createAccessList never traces the call. createAccessList runs the tx through DoCall (a plain EthCall gRPC query, no tracer attached) and then builds newTracer from the input access list, so newTracer.Equal(prevTracer) is true on the first iteration and the method returns whatever access list the caller passed in (empty by default). No SLOAD/SSTORE/EXT*/BALANCE/CALL target is ever recorded.

evm/rpc/backend/tx_info.go

Lines 480 to 494 in 469142d

for {
accessList := prevTracer.AccessList()
traceArgs.AccessList = &accessList
res, err := b.DoCall(ctx, *traceArgs, blockNum, overrides)
if err != nil {
b.Logger.Error("failed to apply transaction", "error", err)
return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", traceArgs.ToTransaction(ethtypes.LegacyTxType).Hash(), err)
}
// Check if access list has converged (no new addresses/slots accessed)
newTracer := logger.NewAccessListTracer(accessList, addressesToExclude)
if newTracer.Equal(prevTracer) {
b.Logger.Info("access list converged", "accessList", accessList)
var vmErr error
if res.VmError != "" {

for {
    accessList := prevTracer.AccessList()
    traceArgs.AccessList = &accessList
    res, err := b.DoCall(ctx, *traceArgs, blockNum, overrides)       // no tracer involved
    ...
    newTracer := logger.NewAccessListTracer(accessList, addressesToExclude) // built from the input, not from execution
    if newTracer.Equal(prevTracer) {                                  // always true
        return accessList, res.GasUsed, vmErr, nil
    }

In go-ethereum the tracer is passed to the EVM via vm.Config{Tracer: tracer.Hooks()} and tracer.Equal(prevTracer) compares what was actually touched. Here nothing bridges the tracer to ApplyMessageWithConfig.

Reproduction (for bugs)

main (469142d), ./local_node.sh -y, dev account 0xc6fe5d33615a1c52c08018c47e8bc53646a0e101.

  1. Deploy a contract whose runtime is PUSH20 0x1111…1111; BALANCE; STOP (touches another account, which geth reports in the access list):
eth_sendTransaction {"from":"0xc6fe…e101","data":"0x6017600c60003960176000f37311111111111111111111111111111111111111113100","gas":"0x30000"}
-> deployed at 0xe2f81b30e1d47dffdbb6ab41ec5f0572705b026d
  1. Ask for the access list:
eth_createAccessList [{"from":"0xc6fe…e101","to":"0xe2f81b30…026d","data":"0x"},"latest"]
-> {"accessList":[],"gasUsed":"0x5c33"}

geth returns [{"address":"0x1111111111111111111111111111111111111111","storageKeys":[]}] for the same call.

  1. Pass a bogus list in; it comes back unchanged (and the call is even charged for it):
eth_createAccessList [{"from":…,"to":"0xe2f81b30…026d","data":"0x","accessList":[{"address":"0xdeaddeaddeaddeaddeaddeaddeaddeaddeaddead","storageKeys":["0x…01"]}]},"latest"]
-> {"accessList":[{"address":"0xdeaddeaddeaddeaddeaddeaddeaddeaddeaddead","storageKeys":["0x…01"]}],"gasUsed":"0x6cff"}

The unit test TestCreateAccessList only checks that a result is returned, so it does not catch this.

Impact

The method has been a no-op since it was added (#346). Clients that rely on it to build EIP-2930 access lists (ethers populateTransaction, viem prepareTransactionRequest with accessList, MEV/simulation tooling) silently get an empty or unchanged list, so the "optimized" transactions never get the expected gas savings.

Fixing it needs the tracer to run inside the EVM: either an EthCall/TraceCall variant in x/vm that installs logger.NewAccessListTracer(...).Hooks() as tracingHooks in ApplyMessageWithConfig and returns the list, or deriving the list from a prestateTracer debug_traceCall (accounts + storage keys minus the exclude set). I can send a PR for either approach if you tell me which one you prefer.

Related

Checklist

  • Linked to a GitHub Issue (or this is the Issue)
  • Repro steps included (for bugs)
  • Impact described
  • I understand minor typo/style doc fixes will not be accepted

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions