-
Notifications
You must be signed in to change notification settings - Fork 83
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Magic: StorageAccessbile Based Simulations (#1831)
Follow up to #1827 (comment) - thanks @fleupold for the wonderful idea! This PR changes instances of `eth_call` with state override simulations **where we are only overriding the Settlement contract code** to make use of `StorageAccessible`. It does this with an additional support `Reader` contract in order to avoid needing to manage deployments on-chain for the `StorageAccessible` target (i.e. the reader logic). See the comment in the `Reader.sol` file for more details on how this works. Specifically, we changed the following two simulations to no longer require state overrides (i.e. we do not need a special node to handle those requests, and it will Just Work™ on Gnosis Chain): * Account balance simulations with pre-hooks * ERC-1271 signature validation with pre-hooks In a follow up PRs I will: 1. #1832 2. Remove the redundant `Web3` strategy for both account balance and signature verification simulation ### Release notes Hooks E2E test continues to pass **without the nasty `----account-balances-optimistic-pre-interaction-handling=true` hack** which used to disable balance checks for orders with pre-hooks. This means that not only are we E2E testing that executing orders with pre-hooks are working, we are also checking that balance simulations work 🎉. You can double check this is actually doing something by applying a patch like this: ```diff diff --git a/crates/e2e/tests/e2e/hooks.rs b/crates/e2e/tests/e2e/hooks.rs index 42d8d072..84d978b5 100644 --- a/crates/e2e/tests/e2e/hooks.rs +++ b/crates/e2e/tests/e2e/hooks.rs @@ -66,7 +66,7 @@ async fn test(web3: Web3) { full: json!({ "metadata": { "hooks": { - "pre": [permit, steal_cow], + "pre": [/*permit, */steal_cow], "post": [steal_weth], }, }, ``` And see the E2E test fail as expected with: ``` thread 'hooks::local_node_test' panicked at 'called `Result::unwrap()` on an `Err` value: (400, "{\"errorType\":\"InsufficientAllowance\",\"description\":\"order owner must give allowance to VaultRelayer\"}")', crates/e2e/tests/e2e/hooks.rs:83:41 ``` I also ran the `cargo test -p shared -- --nocapture --ignored account_balances::simulation` manual test which continues to work.
- Loading branch information
Nicholas Rodrigues Lordello
authored
Sep 6, 2023
1 parent
27fa754
commit fab0fe4
Showing
16 changed files
with
158 additions
and
215 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"abi":[{"inputs":[{"internalType":"contract IStorageAccessible","name":"target","type":"address"},{"internalType":"bytes","name":"code","type":"bytes"},{"internalType":"bytes","name":"call","type":"bytes"}],"stateMutability":"nonpayable","type":"constructor"}],"bytecode":"0x608060405234801561001057600080fd5b5060405161027e38038061027e83398101604081905261002f9161017d565b600082516020840134f090506000846001600160a01b031663f84436bd83856040518363ffffffff1660e01b815260040161006b9291906101ff565b6000604051808303816000875af115801561008a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526100b29190810190610241565b9050805181602001f35b634e487b7160e01b600052604160045260246000fd5b60005b838110156100ed5781810151838201526020016100d5565b50506000910152565b600082601f83011261010757600080fd5b81516001600160401b0380821115610121576101216100bc565b604051601f8301601f19908116603f01168101908282118183101715610149576101496100bc565b8160405283815286602085880101111561016257600080fd5b6101738460208301602089016100d2565b9695505050505050565b60008060006060848603121561019257600080fd5b83516001600160a01b03811681146101a957600080fd5b60208501519093506001600160401b03808211156101c657600080fd5b6101d2878388016100f6565b935060408601519150808211156101e857600080fd5b506101f5868287016100f6565b9150509250925092565b60018060a01b0383168152604060208201526000825180604084015261022c8160608501602087016100d2565b601f01601f1916919091016060019392505050565b60006020828403121561025357600080fd5b81516001600160401b0381111561026957600080fd5b610275848285016100f6565b94935050505056fe","deployedBytecode":"0x6080604052600080fdfea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.17; | ||
|
||
import { IStorageAccessible } from "./interfaces/IStorageAccessible.sol"; | ||
|
||
/// @title A contract for simulating arbitrary code in the context of a | ||
/// `StorageAccessible` contract. | ||
contract SimulateCode { | ||
/// @dev This looks like a constructor but it is not... In fact, nodes | ||
/// support `eth_call`s for contract creation and **return the code of the | ||
/// contract that would be created**. This means we can use constructors to | ||
/// execute arbitrary code on the current state of the EVM, and "manually" | ||
/// return with some inline assembly that data (as this is the mechanism | ||
/// used for contract creation). See the `FetchBlock.sol` contract for | ||
/// another application of this trick. | ||
/// | ||
/// The contract does this to: | ||
/// 1. Deploy some arbitrary contract code | ||
/// 2. Use the `StorageAccessible` pattern to execute the contract code | ||
/// deployed in step 1. within the another contract context (usually the | ||
/// settlement contract - which implements this pattern) | ||
/// | ||
/// This allows us to make use of `StorageAccessible` without actually | ||
/// deploying a contract :). | ||
/// | ||
/// Returns the return data from the simulation code. | ||
/// | ||
/// @param target - The `StorageAccessible` implementation. | ||
/// @param code - Creation code for the reader contract. | ||
/// @param call - The calldata to pass in the `DELEGATECALL` simulation. | ||
constructor( | ||
IStorageAccessible target, | ||
bytes memory code, | ||
bytes memory call | ||
) { | ||
address implementation; | ||
assembly { | ||
implementation := create(callvalue(), add(code, 32), mload(code)) | ||
} | ||
|
||
bytes memory result = target.simulateDelegatecall(implementation, call); | ||
assembly { | ||
return(add(32, result), mload(result)) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.17; | ||
|
||
/// @title Storage accessible interface. | ||
interface IStorageAccessible { | ||
function simulateDelegatecall(address reader, bytes memory call) external returns (bytes memory result); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
//! Module to help encoding `eth_call`s for the `StorageAccessible` contracts. | ||
use { | ||
crate::support::SimulateCode, | ||
ethcontract::{ | ||
common::abi, | ||
tokens::Tokenize, | ||
web3::types::{Bytes, CallRequest}, | ||
H160, | ||
}, | ||
}; | ||
|
||
/// Encode a call to a `StorageAccessible` `target` to execute `call` with the | ||
/// contract created with `code` | ||
pub fn call(target: H160, code: Bytes, call: Bytes) -> CallRequest { | ||
// Unfortunately, the `ethcontract` crate does not expose the logic to build | ||
// creation code for a contract. Luckily, it isn't complicated - you just | ||
// append the ABI-encoded constructor arguments. | ||
let args = abi::encode(&[ | ||
target.into_token(), | ||
ethcontract::Bytes(code.0).into_token(), | ||
ethcontract::Bytes(call.0).into_token(), | ||
]); | ||
|
||
CallRequest { | ||
data: Some( | ||
[ | ||
SimulateCode::raw_contract() | ||
.bytecode | ||
.to_bytes() | ||
.unwrap() | ||
.0 | ||
.as_slice(), | ||
&args, | ||
] | ||
.concat() | ||
.into(), | ||
), | ||
..Default::default() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.