diff --git a/examples/erc20/README.md b/examples/erc20/README.md index b83e5c1d..8758c67a 100644 --- a/examples/erc20/README.md +++ b/examples/erc20/README.md @@ -83,7 +83,7 @@ fn main() { env::commit_slice(&view_call_env.block_commitment().abi_encode()); // Execute the view call; it returns the result in the type generated by the `sol!` macro. - let returns = view_call_env.execute(ViewCall::new(CALL, CONTRACT).with_caller(CALLER)); + let returns = view_call_env.execute(ViewCall::new(CALL, CONTRACT).from(CALLER)); println!("View call result: {}", returns._0); } ``` @@ -101,7 +101,7 @@ let mut env = EthViewCallEnv::from_rpc(&RPC_URL, None)? // Preflight the view call to construct the input that is required to execute the function in // the guest. It also returns the result of the call. -let returns = env.preflight(ViewCall::new(CALL, CONTRACT).with_caller(CALLER))?; +let returns = env.preflight(ViewCall::new(CALL, CONTRACT).from(CALLER))?; let input = env.into_zkvm_input()?; ``` diff --git a/examples/erc20/host/src/main.rs b/examples/erc20/host/src/main.rs index 5bc78886..4cafb830 100644 --- a/examples/erc20/host/src/main.rs +++ b/examples/erc20/host/src/main.rs @@ -61,7 +61,7 @@ fn main() -> Result<()> { // Preflight the view call to construct the input that is required to execute the function in // the guest. It also returns the result of the call. - let returns = env.preflight(ViewCall::new(CALL, CONTRACT).with_caller(CALLER))?; + let returns = env.preflight(ViewCall::new(CALL, CONTRACT).from(CALLER))?; let input = env.into_zkvm_input()?; println!("For block {} `{}` returns: {}", number, IERC20::balanceOfCall::SIGNATURE, returns._0); diff --git a/examples/erc20/methods/guest/src/main.rs b/examples/erc20/methods/guest/src/main.rs index 4781a5e1..f5c53c58 100644 --- a/examples/erc20/methods/guest/src/main.rs +++ b/examples/erc20/methods/guest/src/main.rs @@ -55,6 +55,6 @@ fn main() { env::commit_slice(&view_call_env.block_commitment().abi_encode()); // Execute the view call; it returns the result in the type generated by the `sol!` macro. - let returns = view_call_env.execute(ViewCall::new(CALL, CONTRACT).with_caller(CALLER)); + let returns = view_call_env.execute(ViewCall::new(CALL, CONTRACT).from(CALLER)); println!("View call result: {}", returns._0); } diff --git a/steel/README.md b/steel/README.md index 3e950d4c..b13cb54d 100644 --- a/steel/README.md +++ b/steel/README.md @@ -49,7 +49,7 @@ fn main() { env::commit_slice(&view_call_env.block_commitment().abi_encode()); // Execute the view call; it returns the result in the type generated by the `sol!` macro. - let returns = view_call_env.execute(ViewCall::new(CALL, CONTRACT).with_caller(CALLER)); + let returns = view_call_env.execute(ViewCall::new(CALL, CONTRACT).from(CALLER)); println!("View call result: {}", returns._0); } ``` @@ -67,7 +67,7 @@ let mut env = EthViewCallEnv::from_rpc(&RPC_URL, None)? // Preflight the view call to construct the input that is required to execute the function in // the guest. It also returns the result of the call. -let returns = env.preflight(ViewCall::new(CALL, CONTRACT).with_caller(CALLER))?; +let returns = env.preflight(ViewCall::new(CALL, CONTRACT).from(CALLER))?; let input = env.into_zkvm_input()?; ``` diff --git a/steel/src/host/mod.rs b/steel/src/host/mod.rs index d26ee4c0..ce17f0ee 100644 --- a/steel/src/host/mod.rs +++ b/steel/src/host/mod.rs @@ -86,9 +86,10 @@ impl ViewCall { } impl ViewCallEnv, P::Header> { - /// Executes the call to derive the corresponding [ViewCallInput]. + /// Executes the call using context from the environment. /// - /// This method is used to preflight the call and get the required input for the guest. + /// This method is used to preflight the call. It will retrieve all necessary chain state data + /// using the specified [Provider]. pub fn preflight(&mut self, view_call: ViewCall) -> anyhow::Result { info!( "Executing preflight for '{}' with caller {} on contract {}", @@ -103,7 +104,10 @@ impl ViewCallEnv, P::Header> { .map_err(|err| anyhow!(err)) } - /// Convert the env into input that can be passed to the guest program. + /// Converts the environment into a [ViewCallInput]. + /// + /// The resulting input contains inclusion proofs for all the required chain state data. It can + /// therefore be used to execute the same calls in a verifiable way in the zkVM. pub fn into_zkvm_input(self) -> anyhow::Result> { let db = &self.db; diff --git a/steel/src/lib.rs b/steel/src/lib.rs index 52773f0f..6c88daf6 100644 --- a/steel/src/lib.rs +++ b/steel/src/lib.rs @@ -141,11 +141,9 @@ impl ViewCallEnv { } impl ViewCallEnv { - /// Execute the call on the [ViewCallEnv]. This might modify the database - pub fn execute(&self, view_call: ViewCall) -> C::Return - where - C: SolCall, - { + /// Executes the call using context from the environment. + #[inline] + pub fn execute(&self, view_call: ViewCall) -> C::Return { let db = WrapStateDb::new(&self.db); view_call .transact(db, self.cfg_env.clone(), self.header.inner()) @@ -153,12 +151,15 @@ impl ViewCallEnv { } } -/// A view call to an Ethereum contract. +/// A builder for calling an Ethereum contract. #[derive(Debug, Clone)] pub struct ViewCall { call: C, contract: Address, caller: Address, + gas_limit: u64, + gas_price: U256, + value: U256, } impl ViewCall { @@ -167,8 +168,8 @@ impl ViewCall { mem::size_of::() > 0, "Function call must have a return value" ); - /// The default gas limit for view calls. - const GAS_LIMIT: u64 = 30_000_000; + /// The default gas limit for function calls. + const DEFAULT_GAS_LIMIT: u64 = 30_000_000; /// Creates a new view call to the given contract. pub fn new(call: C, contract: Address) -> Self { @@ -179,15 +180,46 @@ impl ViewCall { call, contract, caller: contract, + gas_limit: Self::DEFAULT_GAS_LIMIT, + gas_price: U256::ZERO, + value: U256::ZERO, } } - /// Sets the caller of the view function. + /// Sets the caller of the function call. + #[deprecated( + since = "0.11.0", + note = "please use `.from(..)` (ViewCall::from) instead" + )] pub fn with_caller(mut self, caller: Address) -> Self { self.caller = caller; self } + /// Sets the caller of the function call. + pub fn from(mut self, from: Address) -> Self { + self.caller = from; + self + } + + /// Sets the gas limit of the function call. + pub fn gas(mut self, gas: u64) -> Self { + self.gas_limit = gas; + self + } + + /// Sets the gas price of the function call. + pub fn gas_price(mut self, gas_price: U256) -> Self { + self.gas_price = gas_price; + self + } + + /// Sets the value field of the function call. + pub fn value(mut self, value: U256) -> Self { + self.value = value; + self + } + /// Executes the view call using the given environment. #[inline] #[deprecated( @@ -198,7 +230,7 @@ impl ViewCall { env.execute(self) } - /// Executes a view call using context from the [ViewCallEnv]. + /// Executes the call for the provided state. fn transact( self, db: D, @@ -218,9 +250,10 @@ impl ViewCall { let tx_env = evm.tx_mut(); tx_env.caller = self.caller; - tx_env.gas_limit = Self::GAS_LIMIT; + tx_env.gas_limit = self.gas_limit; + tx_env.gas_price = self.gas_price; tx_env.transact_to = TransactTo::call(self.contract); - tx_env.value = U256::ZERO; + tx_env.value = self.value; tx_env.data = self.call.abi_encode().into(); let ResultAndState { result, .. } = evm diff --git a/steel/tests/view_call.rs b/steel/tests/view_call.rs index 6e68fc1d..eaea8003 100644 --- a/steel/tests/view_call.rs +++ b/steel/tests/view_call.rs @@ -116,7 +116,7 @@ fn uniswap_exact_output_single() { }, }; - let view_call = ViewCall::new(call, contract).with_caller(caller); + let view_call = ViewCall::new(call, contract).from(caller); let result = eth_call(view_call, block); assert_eq!(result.amountIn, uint!(112537714517_U256)); } @@ -217,7 +217,18 @@ fn chainid() { ViewCall::new(ViewCallTest::testChainidCall {}, VIEW_CALL_TEST_CONTRACT), VIEW_CALL_TEST_BLOCK, ); - assert_eq!(result._0, uint!(11155111_U256),); + assert_eq!(result._0, uint!(11155111_U256)); +} + +#[test] +fn gasprice() { + let gas_price = uint!(42_U256); + let result = eth_call( + ViewCall::new(ViewCallTest::testGaspriceCall {}, VIEW_CALL_TEST_CONTRACT) + .gas_price(gas_price), + VIEW_CALL_TEST_BLOCK, + ); + assert_eq!(result._0, gas_price); } #[test] @@ -229,7 +240,7 @@ fn multi_contract_calls() { ), VIEW_CALL_TEST_BLOCK, ); - assert_eq!(result._0, uint!(84_U256),); + assert_eq!(result._0, uint!(84_U256)); } #[test]