simular_core/lib.rs
1//! This library provides a simple API for interacting with an embedded Ethereum Virtual Machine (EVM).
2//!
3//! <br/>
4//!
5//! # Supports
6//! - Both an in-memory database and the ability to fork state from a remote node
7//! - Snapshot of EVM state for later use
8//! - Both raw encoding/decoding of function calls as well as [alloy SolTypes](https://docs.rs/alloy-sol-macro/0.7.0/alloy_sol_macro/macro.sol.html)
9//! - Lightweight creation of ABI from [human-readable](https://docs.ethers.org/v5/api/utils/abi/formats/#abi-formats--human-readable-abi) syntax
10//!
11//!
12//! # Examples
13//!
14//! - Create and interact with the EVM using the the in-memory database.
15//!
16//! ```
17//! use simular_core::{BaseEvm, generate_random_addresses};
18//! use alloy_primitives::{Address, U256};
19//!
20//! // Generate some random addresses
21//! let addresses = generate_random_addresses(2);
22//! let bob = addresses[0];
23//! let alice = addresses[1];
24//!
25//! // create the EVM with in-memory database (default)
26//! let mut evm = BaseEvm::default();
27//!
28//! // create 2 accounts. Bob w/ 2 ether, alice w/ none
29//! evm.create_account(bob, Some(U256::from(2e18))).unwrap();
30//! evm.create_account(alice, None).unwrap();
31//!
32//! // check the balances
33//! assert!(evm.get_balance(bob).unwrap() == U256::from(2e18));
34//! assert!(evm.get_balance(alice).unwrap() == U256::from(0));
35//! ```
36//!
37//! - Fork a remote contract. Interacting with a remote contract pulls the state of the remote contract
38//! into the local in-memory database for use.
39//!
40//! ```
41//! use simular_core::{BaseEvm, generate_random_addresses, ContractAbi;
42//! use alloy_primitives::{Address, U256, address};
43//!
44//! let abi = ContractAbi::from_human_readable(vec![
45//! "function totalSupply() (uint256)"
46//! ]);
47//!
48//!
49//! // create a fork using the latest block
50//! let fork_info = CreateFork.latest_block(URL OF JSON-RPC NODE);
51//! let mut evm = BaseEvm::new(Some(fork_info));
52//!
53//! // remote contract address.
54//! // using DAI: 0x6B175474E89094C44Da98b954EedeAC495271d0F
55//! let contract_address = address!("6B175474E89094C44Da98b954EedeAC495271d0F");
56//!
57//! // encode the function call
58//! let (encoded_total_supply, _, decoder) =
59//! abi.encode_function("totalSupply", "()").unwrap();
60//!
61//! // call the function on the remote contract
62//! let output = evm.transact_call(
63//! contract_address,
64//! encoded_total_supply,
65//! U256::from(0)).unwrap();
66//!
67//! // decode the result
68//! let value = decoder.unwrap().abi_decode(&output.result)
69//!
70//! println!("total supply: {:?}", value);
71//! ```
72//!
73pub mod abi;
74pub mod db;
75pub mod errors;
76pub mod evm;
77pub mod snapshot;
78
79// re-exports
80pub use {abi::ContractAbi, db::CreateFork, evm::BaseEvm, snapshot::SnapShot};
81
82use alloy_primitives::Address;
83
84/// Generate the given `num` of addresses
85pub fn generate_random_addresses(num: u8) -> Vec<Address> {
86 let mut addresses: Vec<alloy_primitives::Address> = Vec::new();
87 for i in 1..=num {
88 addresses.push(Address::repeat_byte(i));
89 }
90 addresses
91}