Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add more config options for Steel calls #113

Merged
merged 1 commit into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/erc20/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
```
Expand All @@ -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()?;
```

Expand Down
2 changes: 1 addition & 1 deletion examples/erc20/host/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion examples/erc20/methods/guest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
4 changes: 2 additions & 2 deletions steel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
```
Expand All @@ -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()?;
```

Expand Down
10 changes: 7 additions & 3 deletions steel/src/host/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ impl<C: SolCall> ViewCall<C> {
}

impl<P: Provider> ViewCallEnv<ProofDb<P>, 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<C: SolCall>(&mut self, view_call: ViewCall<C>) -> anyhow::Result<C::Return> {
info!(
"Executing preflight for '{}' with caller {} on contract {}",
Expand All @@ -103,7 +104,10 @@ impl<P: Provider> ViewCallEnv<ProofDb<P>, 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<ViewCallInput<P::Header>> {
let db = &self.db;

Expand Down
57 changes: 45 additions & 12 deletions steel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,24 +141,25 @@ impl<D, H: EvmHeader> ViewCallEnv<D, H> {
}

impl<H: EvmHeader> ViewCallEnv<StateDB, H> {
/// Execute the call on the [ViewCallEnv]. This might modify the database
pub fn execute<C>(&self, view_call: ViewCall<C>) -> C::Return
where
C: SolCall,
{
/// Executes the call using context from the environment.
#[inline]
pub fn execute<C: SolCall>(&self, view_call: ViewCall<C>) -> C::Return {
let db = WrapStateDb::new(&self.db);
view_call
.transact(db, self.cfg_env.clone(), self.header.inner())
.unwrap()
}
}

/// A view call to an Ethereum contract.
/// A builder for calling an Ethereum contract.
#[derive(Debug, Clone)]
pub struct ViewCall<C: SolCall> {
call: C,
contract: Address,
caller: Address,
gas_limit: u64,
gas_price: U256,
value: U256,
}

impl<C: SolCall> ViewCall<C> {
Expand All @@ -167,8 +168,8 @@ impl<C: SolCall> ViewCall<C> {
mem::size_of::<C::Return>() > 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 {
Expand All @@ -179,15 +180,46 @@ impl<C: SolCall> ViewCall<C> {
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(
Expand All @@ -198,7 +230,7 @@ impl<C: SolCall> ViewCall<C> {
env.execute(self)
}

/// Executes a view call using context from the [ViewCallEnv].
/// Executes the call for the provided state.
fn transact<D, H>(
self,
db: D,
Expand All @@ -218,9 +250,10 @@ impl<C: SolCall> ViewCall<C> {

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
Expand Down
17 changes: 14 additions & 3 deletions steel/tests/view_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down Expand Up @@ -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]
Expand All @@ -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]
Expand Down
Loading