snark_verifier/loader/evm/util/
executor.rs

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