Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

feat: allow balance, code, nonce, and state overrides in eth_call #2565

Merged
merged 51 commits into from
Apr 20, 2022

Conversation

domob1812
Copy link
Contributor

@domob1812 domob1812 commented Mar 9, 2022

This PR adds support for overriding the contract code and storage and the account balance and nonce for simulations with eth_call. This feature is similarly supported by geth.

The eth_call RPC method now accepts a third override parameter which is a map from an address to the desired state of that address. The state object has the following keys, all of which are optional:

balance: QUANTITY - The balance to set for the account before executing the call.
nonce: QUANTITY - The nonce to set for the account before executing the call.
code: DATA - The EVM bytecode to set for the account before executing the call.
state*: OBJECT - Key-value mapping of storage slot to value that will clear all slots and then override individual slots in the account storage before executing the call.
stateDiff*: OBJECT - Key-value mapping of storage slot to value that will override individual slots in the account storage before executing the call.
*Note - state and stateDiff fields are mutually exclusive.

So, an example override object using all fields overriding multiple addresses could look like the following:

{
  "0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3": { 
    "nonce": "0xa", 
    "balance": "0xffff", 
    "state": { 
      "0000000000000000000000000000000000000000000000000000000000000001": "0xbaddad42baddad42baddad42baddad42baddad42baddad42baddad42baddad42"
    } 
  },
  "0xebe8efa441b9302a0d7eaecc277c09d20d684540": { 
    "code": "0x123456", 
    "stateDiff": {
      "0000000000000000000000000000000000000000000000000000000000000002": "0xbaddad42baddad42baddad42baddad42baddad42baddad42baddad42baddad42"
    } 
  }
}

Like all state changes made with eth_call, the changes are ephemeral and only last for that specific run of eth_call. We'd like to give a huge thank you to @domob1812 and @dekz for their initial contributions to this one, you both were a huge help.

The PR introducing this feature uses @dekz's #905 as a starting point, and fixes #554 and #2934.

@domob1812
Copy link
Contributor Author

Note that geth also supports overriding storage slots, which this PR does not yet implement (because I personally don't need it and also #905 did not implement it).

I think this can be added as a follow-up when needed. But if you prefer to include support with this PR, let me know and I can try to add it.

@MicaiahReid
Copy link
Contributor

MicaiahReid commented Mar 11, 2022

@domob1812 Thank you for the PR! We are reviewing and adding support for overriding storage slots while we're at it. This should hopefully be available in the next release!

@domob1812
Copy link
Contributor Author

Ok cool, thanks a lot! If you need any help from my side, let me know. I can also work on the storage slots, although I guess you know the involved code much better than me (of course).

Copy link
Member

@davidmurdoch davidmurdoch left a comment

Choose a reason for hiding this comment

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

Looking really great! Exciting to finally see this feature land!

I've requested some changes. Let me know if either of you (@domob1812 @MicaiahReid ) have questions or disagree with any of my comments!

src/chains/ethereum/ethereum/src/blockchain.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/blockchain.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/blockchain.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/api.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/blockchain.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/blockchain.ts Outdated Show resolved Hide resolved
@davidmurdoch davidmurdoch force-pushed the develop branch 3 times, most recently from 96d6c7f to 47d583d Compare April 8, 2022 17:42
@MicaiahReid
Copy link
Contributor

I've done a lot of testing in Geth to see how their eth_call overrides work. Here are the results:

Override Type Tested Value Geth Response
Balance null Balance remains
Balance "" Balance 0
Balance "0x", undefined, "123", {}, 123, -9 Rejected
Code null Code remains
Code "" Clears code
Code "0x" Clears code
Code undefined, "123", {}, 123, -9 Rejected
StateDiff setting value to:null, "0xbaddad42", "", "0x", undefined, "123", {}, 123, -9 Rejected
StateDiff setting slot to:null, "0xbaddad42", "", "0x", undefined, "123", {}, 123, -9 Rejected
State setting value to:null, "0xbaddad42", "", "0x", undefined, "123", {}, 123, -9 Rejected
State setting slot to:null, "0xbaddad42", "", "0x", undefined, "123", {}, 123, -9 Rejected
Nonce null Accepted - makes same contract hash as not overriding nonce
Nonce "" Accepted - sets nonce to "0x0"
Nonce "0x", undefined, "123", {}, 123, -9 Rejected

I've made updates so that Ganache behaves the same way, but there's some very specific data validation that we're now doing in the applySimulationOverrides that makes me wonder if we should have some more general rpc data types that align with Geth's.

Also, we should probably consider matching our evm_setAccountNonce, evm_setAccountBalance, evm_setAccountCode, and evm_setAccountStorageAt implementations to have the same data validation as this.

@davidmurdoch davidmurdoch changed the title feat: Allow contract code and balance overrides feat: allow balance, code, nonce, and state overrides in eth_call Apr 15, 2022
src/chains/ethereum/ethereum/src/api.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/api.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/blockchain.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/blockchain.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/blockchain.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/blockchain.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/blockchain.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/blockchain.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/blockchain.ts Outdated Show resolved Hide resolved
src/chains/ethereum/ethereum/src/api.ts Outdated Show resolved Hide resolved
Copy link
Member

@davidmurdoch davidmurdoch left a comment

Choose a reason for hiding this comment

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

meant to request changes on the last review. so i'm reeviewing again.

@davidmurdoch davidmurdoch changed the base branch from develop to alpha April 20, 2022 19:45
@davidmurdoch davidmurdoch changed the base branch from alpha to develop April 20, 2022 19:45
Copy link
Member

@davidmurdoch davidmurdoch left a comment

Choose a reason for hiding this comment

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

<3

@MicaiahReid MicaiahReid merged commit 037e156 into trufflesuite:develop Apr 20, 2022
@domob1812 domob1812 deleted the rebased-state-override branch April 21, 2022 12:51
davidmurdoch added a commit that referenced this pull request Apr 22, 2022
…2565)

* feat: Allow contract code and balance overrides

Support overriding the contract code, account balances and nonces
for simulations with eth_call.  This is an extension also supported
by geth.

* reorg eth_call override type. add state/stateDiff

* support state/stateDiff in eth_call override

* fix eth_call code override. reorg a bit

* add override structure to eth_call jsdocs

* add override to eth_call example in jsdoc

* prevent use of state & stateDiff on override

* remove unused import on test

* add encodeValue/deployContract helpers

* reorg previous test to make room for new

* add tests for eth_call override

* rename eth_call override type

* change keccak import to be from @ganache/utils

* await async function

* change `Object.entries` to more perfomant `for ... in`

* rename confusing key name

* change `Object.entries` to more performang `for ... in`

* move comment

* data validation for state/Diff override

* add junk data test for eth_call overrides

* remove unused file

* correctly throw on both state && stateDiff

* fix broken test

* remove unused throw

* change return to continue like a smart person

* make state/stateDiff looping more efficient

* fix test name

* abstract override generation in test

* fix override balance test expected value

* fix override code test

* fix override state/stateDiff test data

* fix override stateDiff expected values

* fix override state expected values

* add todo comment

* add bad slot values for state/Diff test

* add junk value test for nonce

* add data validation method for state/Diff override

* validate data for state/Diff override

* fix some default data to match geth

* Move eth_call overrides setting to helper file

* Apply suggestions from code review

Co-authored-by: David Murdoch <187813+davidmurdoch@users.noreply.github.com>

* extract types to run-call helper

* check length directly rather than removing prefix

* use copied trie for eth_call

* fix copy/paste error

* fix copy/paste error

* beef up test a bit

* remove unused libraries

* add tests to confirm eth_call changes are ephemeral

* set multiple slots in test

* make tests more scrict

Co-authored-by: Jacob Evans <jacob@dekz.net>
Co-authored-by: MicaiahReid <micaiahreid@gmail.com>
Co-authored-by: David Murdoch <187813+davidmurdoch@users.noreply.github.com>
davidmurdoch added a commit that referenced this pull request Apr 22, 2022
…2565)

* feat: Allow contract code and balance overrides

Support overriding the contract code, account balances and nonces
for simulations with eth_call.  This is an extension also supported
by geth.

* reorg eth_call override type. add state/stateDiff

* support state/stateDiff in eth_call override

* fix eth_call code override. reorg a bit

* add override structure to eth_call jsdocs

* add override to eth_call example in jsdoc

* prevent use of state & stateDiff on override

* remove unused import on test

* add encodeValue/deployContract helpers

* reorg previous test to make room for new

* add tests for eth_call override

* rename eth_call override type

* change keccak import to be from @ganache/utils

* await async function

* change `Object.entries` to more perfomant `for ... in`

* rename confusing key name

* change `Object.entries` to more performang `for ... in`

* move comment

* data validation for state/Diff override

* add junk data test for eth_call overrides

* remove unused file

* correctly throw on both state && stateDiff

* fix broken test

* remove unused throw

* change return to continue like a smart person

* make state/stateDiff looping more efficient

* fix test name

* abstract override generation in test

* fix override balance test expected value

* fix override code test

* fix override state/stateDiff test data

* fix override stateDiff expected values

* fix override state expected values

* add todo comment

* add bad slot values for state/Diff test

* add junk value test for nonce

* add data validation method for state/Diff override

* validate data for state/Diff override

* fix some default data to match geth

* Move eth_call overrides setting to helper file

* Apply suggestions from code review

Co-authored-by: David Murdoch <187813+davidmurdoch@users.noreply.github.com>

* extract types to run-call helper

* check length directly rather than removing prefix

* use copied trie for eth_call

* fix copy/paste error

* fix copy/paste error

* beef up test a bit

* remove unused libraries

* add tests to confirm eth_call changes are ephemeral

* set multiple slots in test

* make tests more scrict

Co-authored-by: Jacob Evans <jacob@dekz.net>
Co-authored-by: MicaiahReid <micaiahreid@gmail.com>
Co-authored-by: David Murdoch <187813+davidmurdoch@users.noreply.github.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for eth_call state-overrides
4 participants