snark_verifier/loader/evm/util/
executor.rs

1use revm::primitives::TxKind;
2use revm::{
3    primitives::{ExecutionResult, Output, TransactTo, TxEnv},
4    Context, Evm, Handler, InMemoryDB,
5};
6
7/// Deploy contract and then call with calldata.
8/// Returns gas_used of call to deployed contract if both transactions are successful.
9pub fn deploy_and_call(deployment_code: Vec<u8>, calldata: Vec<u8>) -> Result<u64, String> {
10    let mut evm =
11        Evm::new(Context::new_with_db(InMemoryDB::default()), Handler::new(Default::default()));
12
13    *evm.tx_mut() = TxEnv {
14        gas_limit: u64::MAX,
15        transact_to: TxKind::Create,
16        data: deployment_code.into(),
17        ..Default::default()
18    };
19
20    let result = evm.transact_commit().unwrap();
21    let contract = match result {
22        ExecutionResult::Success {
23            output: Output::Create(_, Some(contract)),
24            ..
25        } => contract,
26        ExecutionResult::Revert { gas_used, output } => {
27            return Err(format!(
28                "Contract deployment transaction reverts with gas_used {gas_used} and output {:#x}",
29                output
30            ))
31        }
32        ExecutionResult::Halt { reason, gas_used } => return Err(format!(
33                "Contract deployment transaction halts unexpectedly with gas_used {gas_used} and reason {:?}",
34                reason
35            )),
36        _ => unreachable!(),
37    };
38
39    *evm.tx_mut() = TxEnv {
40        gas_limit: u64::MAX,
41        transact_to: TransactTo::Call(contract),
42        data: calldata.into(),
43        ..Default::default()
44    };
45
46    let result = evm.transact_commit().unwrap();
47    match result {
48        ExecutionResult::Success { gas_used, .. } => Ok(gas_used),
49        ExecutionResult::Revert { gas_used, output } => Err(format!(
50            "Contract call transaction reverts with gas_used {gas_used} and output {:#x}",
51            output
52        )),
53        ExecutionResult::Halt { reason, gas_used } => Err(format!(
54            "Contract call transaction halts unexpectedly with gas_used {gas_used} and reason {:?}",
55            reason
56        )),
57    }
58}