example_contract_deployment/
main.rs#![cfg_attr(not(test), warn(unused_crate_dependencies))]
use anyhow::{anyhow, bail};
use database::CacheDB;
use revm::{
bytecode::opcode,
context::Context,
context_interface::result::{ExecutionResult, Output},
database_interface::EmptyDB,
handler::EthHandler,
primitives::{hex, Bytes, TxKind, U256},
EvmCommit, MainEvm,
};
const INIT_CODE: &[u8] = &[
opcode::PUSH1,
0x01,
opcode::PUSH1,
0x17,
opcode::PUSH1,
0x1f,
opcode::CODECOPY,
opcode::PUSH0,
opcode::MLOAD,
opcode::PUSH0,
opcode::SSTORE,
];
const RET: &[u8] = &[
opcode::PUSH1,
0x02,
opcode::PUSH1,
0x15,
opcode::PUSH0,
opcode::CODECOPY,
opcode::PUSH1,
0x02,
opcode::PUSH0,
opcode::RETURN,
];
const RUNTIME_BYTECODE: &[u8] = &[opcode::PUSH0, opcode::SLOAD];
fn main() -> anyhow::Result<()> {
let param = 0x42;
let bytecode: Bytes = [INIT_CODE, RET, RUNTIME_BYTECODE, &[param]].concat().into();
let mut evm = MainEvm::new(
Context::builder()
.modify_tx_chained(|tx| {
tx.transact_to = TxKind::Create;
tx.data = bytecode.clone();
})
.with_db(CacheDB::<EmptyDB>::default()),
EthHandler::default(),
);
println!("bytecode: {}", hex::encode(bytecode));
let ref_tx = evm.exec_commit()?;
let ExecutionResult::Success {
output: Output::Create(_, Some(address)),
..
} = ref_tx
else {
bail!("Failed to create contract: {ref_tx:#?}");
};
println!("Created contract at {address}");
evm.context.modify_tx(|tx| {
tx.transact_to = TxKind::Call(address);
tx.data = Default::default();
tx.nonce += 1;
});
let result = evm.transact()?;
let Some(storage0) = result
.state
.get(&address)
.ok_or_else(|| anyhow!("Contract not found"))?
.storage
.get::<U256>(&Default::default())
else {
bail!("Failed to write storage in the init code: {result:#?}");
};
println!("storage U256(0) at {address}: {storage0:#?}");
assert_eq!(storage0.present_value(), param.try_into()?, "{result:#?}");
Ok(())
}