Skip to content

Support state_override in eth_call and eth_estimateGas#629

Merged
lukasz-zimnoch merged 15 commits intomainfrom
state-override
Mar 30, 2026
Merged

Support state_override in eth_call and eth_estimateGas#629
lukasz-zimnoch merged 15 commits intomainfrom
state-override

Conversation

@pdyraga
Copy link
Copy Markdown
Member

@pdyraga pdyraga commented Mar 26, 2026

Introduction

The pull request adds support for state_override in eth_call and eth_estimateGas methods.

Changes

The structure of stateOverride is based on the version from go-ethereum. I have also added SetBalance and SetStorage to StateDB, just like go-ethereum does. State overrides are optional and applied in ApplyMessageWithConfig, where we make sure state overrides can only be used for calls not committing the state.

Testing

Run the node locally with $ make localnet-bin-start and execute eth_call with state_override. Compare the outcome with one returned by RPC providers running the main version of the code.

curl -s -X POST http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "eth_call",
    "params": [
      {
        "to": "0x000000000000000000000000000000000000abcd",
        "data": "0x70a0823100000000000000000000000000000000000000000000000000000000deadbeef"
      },
      "latest",
      {
        "0x000000000000000000000000000000000000abcd": {
          "code": "0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c806370a082311161008c57806395d89b411161006657806395d89b41146101d8578063a9059cbb146101e0578063dd62ed3e146101f3578063f2fde38b1461022c57600080fd5b806370a082311461018c578063715018a6146101b55780638da5cb5b146101bd57600080fd5b806323b872dd116100c857806323b872dd14610142578063313ce5671461015557806340c10f191461016457806342966c681461017957600080fd5b806306fdde03146100ef578063095ea7b31461010d57806318160ddd14610130575b600080fd5b6100f761023f565b604051610104919061077d565b60405180910390f35b61012061011b3660046107e7565b6102d1565b6040519015158152602001610104565b6002545b604051908152602001610104565b610120610150366004610811565b6102eb565b60405160128152602001610104565b6101776101723660046107e7565b61030f565b005b61017761018736600461084e565b610325565b61013461019a366004610867565b6001600160a01b031660009081526020819052604090205490565b610177610332565b6005546040516001600160a01b039091168152602001610104565b6100f7610346565b6101206101ee3660046107e7565b610355565b610134610201366004610889565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b61017761023a366004610867565b610363565b60606003805461024e906108bc565b80601f016020809104026020016040519081016040528092919081815260200182805461027a906108bc565b80156102c75780601f1061029c576101008083540402835291602001916102c7565b820191906000526020600020905b8154815290600101906020018083116102aa57829003601f168201915b5050505050905090565b6000336102df8185856103a3565b60019150505b92915050565b6000336102f98582856103b5565b610304858585610434565b506001949350505050565b610317610493565b61032182826104c0565b5050565b61032f33826104f6565b50565b61033a610493565b610344600061052c565b565b60606004805461024e906108bc565b6000336102df818585610434565b61036b610493565b6001600160a01b03811661039a57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b61032f8161052c565b6103b0838383600161057e565b505050565b6001600160a01b0383811660009081526001602090815260408083209386168352929052205460001981101561042e578181101561041f57604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610391565b61042e8484848403600061057e565b50505050565b6001600160a01b03831661045e57604051634b637e8f60e11b815260006004820152602401610391565b6001600160a01b0382166104885760405163ec442f0560e01b815260006004820152602401610391565b6103b0838383610653565b6005546001600160a01b031633146103445760405163118cdaa760e01b8152336004820152602401610391565b6001600160a01b0382166104ea5760405163ec442f0560e01b815260006004820152602401610391565b61032160008383610653565b6001600160a01b03821661052057604051634b637e8f60e11b815260006004820152602401610391565b61032182600083610653565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0384166105a85760405163e602df0560e01b815260006004820152602401610391565b6001600160a01b0383166105d257604051634a1406b160e11b815260006004820152602401610391565b6001600160a01b038085166000908152600160209081526040808320938716835292905220829055801561042e57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161064591815260200190565b60405180910390a350505050565b6001600160a01b03831661067e57806002600082825461067391906108f6565b909155506106f09050565b6001600160a01b038316600090815260208190526040902054818110156106d15760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610391565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b03821661070c5760028054829003905561072b565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161077091815260200190565b60405180910390a3505050565b602081526000825180602084015260005b818110156107ab576020818601810151604086840101520161078e565b506000604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b03811681146107e257600080fd5b919050565b600080604083850312156107fa57600080fd5b610803836107cb565b946020939093013593505050565b60008060006060848603121561082657600080fd5b61082f846107cb565b925061083d602085016107cb565b929592945050506040919091013590565b60006020828403121561086057600080fd5b5035919050565b60006020828403121561087957600080fd5b610882826107cb565b9392505050565b6000806040838503121561089c57600080fd5b6108a5836107cb565b91506108b3602084016107cb565b90509250929050565b600181811c908216806108d057607f821691505b6020821081036108f057634e487b7160e01b600052602260045260246000fd5b50919050565b808201808211156102e557634e487b7160e01b600052601160045260246000fdfea2646970667358221220bf49c55d5ebba2b0fe4fd33086debd7260fad3827fd840b4e195ac55e7e091b964736f6c634300081a0033",
          "stateDiff": {
            "0x49361c85d50c86f43fdb7ff3f85f3cac00c47bda054279b6563a02b9b214ccf4": "0x00000000000000000000000000000000000000000000003635c9adc5dea00000"
          }
        }
      }
    ],
    "id": 1
  }'

Where:

  • 0x00000000000000000000000000000000DeaDBeef - fake address for which we are setting balance
  • 0x000000000000000000000000000000000000abcd - fake address of ERC20 smart contract
  • 0x70a0823100000000000000000000000000000000000000000000000000000000deadbeef - balanceOf(0x...DeaDBeef)
  • 0x6080604052348015610010576000... - ERC20 smart contract bytecode
  • 0x49361c85... storage slot is keccak256(abi.encode(0xDeaDBeef, 0)) - the balance mapping slot for that address

The expected result on this branch is 0x...3635c9adc5dea00000 = 1000 * 10^18.

Calling eth_estimateGas with the same state overrides and calldata for transfer:

    "method": "eth_estimateGas",
    "params": [
      {
        "from": "0x00000000000000000000000000000000DeaDBeef",
        "to": "0x000000000000000000000000000000000000abcd",
        "data": "0xa9059cbb00000000000000000000000000000000000000000000000000000000cafebabe0000000000000000000000000000000000000000000000056bc75e2d63100000"
      },

should yield gas cost estimated.


Author's checklist

  • Provided the appropriate description of the pull request
  • Updated relevant unit and integration tests
  • Updated relevant documentation (docs/) or specification (x/<module>/spec/)
  • Assigned myself in the Assignees field
  • Assigned mezod-developers in the Reviewers field and notified them on Discord

Reviewer's checklist

  • Confirmed all author's checklist items have been addressed
  • Considered security implications of the code changes
  • Considered performance implications of the code changes
  • Tested the changes and summarized covered scenarios and results in a comment

pdyraga added 9 commits March 26, 2026 10:59
state_override is the JSON-encoded state override map for eth_call.
It's an optional field.
Wire the state_override parameter through the eth_call RPC path so
callers can override account nonce, code, balance, and storage when
simulating calls. Add SetBalance and SetStorage methods to StateDB
to support the override logic.
When SetStorage replaces an account's storage, reads of non-overridden
keys fall through to the keeper and return old values. Add a
storageWiped flag on stateObject that makes GetCommittedState return
empty for keys not in the new storage, matching geth's behavior of
marking the old object as destructed.
Just two basic tests for a valid and invalid state override, consistent
with the existing approach in TestEthCall. More thorough tests for
individual steps of state overriding will be added in separate commits.
We don't need to represent State and StateDiff as pointers to a map,
simple map is enough. Same about a double pointer to Balance's bigint.
Three functions in geth support state_override: eth_call,
eth_estimateGas, and eth_createAccessList. The last one is not supported
by mezod but from now on the other two both support state_override.

For eth_estimateGas it was simple as we use the infrastructure added for
eth_call in the previous commits.
Updated documentation to reflect support for state overrides for
eth_call and eth_estimateGas.
@pdyraga pdyraga self-assigned this Mar 26, 2026
@pdyraga pdyraga marked this pull request as ready for review March 26, 2026 12:38
@pdyraga pdyraga requested a review from a team March 26, 2026 12:38
pdyraga added 4 commits March 27, 2026 10:07
These two functions are only used in the context of state overriding
now, and thinking more about it, setting balance or setting storage for
some address to arbitrary values are not usual operations when
a transaction is processed.
When storage is overridden via OverrideStorage, cache the empty hash
in originStorage for consistency with go-ethereum. This ensures
subsequent lookups for the same key hit the cache instead of
re-evaluating the storageOverridden branch.
Move state override handling (JSON deserialization + application) out of
ApplyMessageWithConfig and into the gRPC handlers where it belongs.

Introduce SimulateMessage for read-only simulation (eth_call,
eth_estimateGas) with commit hardcoded to false, and extract a private
applyMessageWithConfig that takes a pre-built StateDB and has no
knowledge of overrides.
Copy link
Copy Markdown
Collaborator

@lukasz-zimnoch lukasz-zimnoch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested and works as advertised! ✅

@lukasz-zimnoch lukasz-zimnoch merged commit 39f5fe1 into main Mar 30, 2026
11 checks passed
@lukasz-zimnoch lukasz-zimnoch deleted the state-override branch March 30, 2026 08:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants