-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathfork_ref_transact.rs
More file actions
84 lines (69 loc) · 3.13 KB
/
Copy pathfork_ref_transact.rs
File metadata and controls
84 lines (69 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! This example demonstrates how to query storage slots of a contract, using
//! [`AlloyDb`].
use alloy::{
eips::BlockId,
primitives::{address, Address, TxKind, U256},
providers::ProviderBuilder,
sol,
sol_types::SolCall,
};
use revm::{context::TxEnv, database::WrapDatabaseAsync};
use trevm::{db::alloy::AlloyDb, revm::database::CacheDB, NoopBlock, NoopCfg, TrevmBuilder, Tx};
sol! {
#[allow(missing_docs)]
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
}
struct GetReservesFiller;
impl Tx for GetReservesFiller {
fn fill_tx_env(&self, tx_env: &mut TxEnv) {
tx_env.caller = Address::with_last_byte(0);
// ETH/USDT pair on Uniswap V2
tx_env.kind = TxKind::Call(POOL_ADDRESS);
// calldata formed via alloy's abi encoder
tx_env.data = getReservesCall::new(()).abi_encode().into();
// transaction value in wei
tx_env.value = U256::from(0);
}
}
const POOL_ADDRESS: Address = address!("0d4a11d5EEaaC28EC3F61d100daF4d40471f1852");
#[tokio::main]
async fn main() -> eyre::Result<()> {
// create ethers client and wrap it in Arc<M>
let rpc_url = "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27";
let client = ProviderBuilder::new().connect_http(rpc_url.parse()?);
// ----------------------------------------------------------- //
// Storage slots of UniV2Pair contract //
// =========================================================== //
// storage[5] = factory: address //
// storage[6] = token0: address //
// storage[7] = token1: address //
// storage[8] = (res0, res1, ts): (uint112, uint112, uint32) //
// storage[9] = price0CumulativeLast: uint256 //
// storage[10] = price1CumulativeLast: uint256 //
// storage[11] = kLast: uint256 //
// =========================================================== //
// initialize new AlloyDB
let alloydb = WrapDatabaseAsync::new(AlloyDb::new(client, BlockId::default())).unwrap();
// initialise empty in-memory-db
let cache_db = CacheDB::new(alloydb);
// initialise an empty (default) EVM
let evm = TrevmBuilder::new()
.with_db(cache_db)
.build_trevm()
.fill_cfg(&NoopCfg)
.fill_block(&NoopBlock)
.fill_tx(&GetReservesFiller)
.run()
.inspect_err(|e| panic!("Execution error {e:?}"))
.unwrap();
// Inspect the outcome of a transaction execution, and get the return value
println!("Execution result: {:#?}", evm.result());
let output = evm.output().expect("Execution halted");
// decode bytes to reserves + ts via alloy's abi decode
let return_vals = getReservesCall::abi_decode_returns_validate(output)?;
// Print emulated getReserves() call output
println!("Reserve0: {:#?}", return_vals.reserve0);
println!("Reserve1: {:#?}", return_vals.reserve1);
println!("Timestamp: {:#?}", return_vals.blockTimestampLast);
Ok(())
}