Skip to content

Commit e3708a3

Browse files
authored
Add optimism feature and update to reth 1.3.0 (#2)
1 parent 54f8ccf commit e3708a3

27 files changed

+1784
-1184
lines changed

Cargo.lock

+1,345-961
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+37-18
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,51 @@ license = "MIT OR Apache-2.0"
66

77
[dependencies]
88
parking_lot = "0.12.3"
9-
revm = { version = "19.5.0", features = ["alloydb"] }
109
tokio = { version = "1.43.0", features = ["rt-multi-thread"] }
1110

11+
# revm
12+
revm = { git = "https://github.com/bluealloy/revm", version = "20.0.0-alpha.5", features = ["alloydb"] }
13+
revm-context = "1.0.0-alpha.4"
14+
revm-database = "1.0.0-alpha.3"
15+
revm-state = "1.0.0-alpha.3"
16+
1217
# alloy
13-
alloy-consensus = "0.11.1"
14-
alloy-eips = "0.11.1"
15-
alloy-network = "0.11.1"
16-
alloy-primitives = "0.8.21"
17-
alloy-provider = "0.11.1"
18-
alloy-rpc-types-eth = "0.11.1"
19-
alloy-transport = "0.11.1"
18+
alloy-consensus = "0.12.5"
19+
alloy-eips = "0.12.5"
20+
alloy-network = "0.12.5"
21+
alloy-primitives = "0.8.23"
22+
alloy-provider = "0.12.5"
23+
alloy-transport = "0.12.5"
24+
25+
# op-alloy
26+
op-alloy-network = { version = "0.11.2", optional = true }
2027

2128
# reth
22-
reth-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v1.2.0" }
23-
reth-db-models = { git = "https://github.com/paradigmxyz/reth", tag = "v1.2.0" }
24-
reth-errors = { git = "https://github.com/paradigmxyz/reth", tag = "v1.2.0" }
25-
reth-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.2.0" }
26-
reth-provider = { git = "https://github.com/paradigmxyz/reth", tag = "v1.2.0" }
27-
reth-trie = { git = "https://github.com/paradigmxyz/reth", tag = "v1.2.0" }
29+
reth-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.0" }
30+
reth-db-models = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.0" }
31+
reth-errors = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.0" }
32+
reth-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.0", features = ["serde-bincode-compat"] }
33+
reth-primitives-traits = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.0" }
34+
reth-provider = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.0" }
35+
reth-trie = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.0" }
36+
37+
# ethereum
38+
reth-ethereum-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.0", features = ["alloy-compat", "reth-codec"] }
2839

2940
# optimism
30-
reth-optimism-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v1.2.0" }
41+
reth-optimism-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.0", optional = true }
42+
reth-optimism-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.0", features = [
43+
"alloy-compat",
44+
"reth-codec",
45+
"serde",
46+
"serde-bincode-compat",
47+
], optional = true }
3148

49+
[features]
50+
optimism = ["op-alloy-network", "reth-optimism-chainspec", "reth-optimism-primitives"]
3251

3352
[dev-dependencies]
34-
alloy-node-bindings = "0.11.1"
53+
alloy-node-bindings = "0.12.5"
3554
eyre = "0.6.12"
36-
reth-revm = { git = "https://github.com/paradigmxyz/reth", tag = "v1.2.0" }
37-
ruint = "1.12.4"
55+
reth-revm = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.0" }
56+
ruint = "1.13.1"

Makefile

+21-7
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,48 @@
1-
.PHONY: build run test clean fmt fmt-check clippy taplo taplo-check deny-check pre-release
2-
1+
.PHONY: build
32
build:
4-
cargo build --all
3+
cargo build --no-default-features
4+
5+
.PHONY: build-op
6+
build-op:
7+
cargo build --features optimism
58

9+
.PHONE: release
610
release:
711
cargo build --release
812

9-
run:
10-
cargo run
11-
13+
.PHONY: test
1214
test:
1315
cargo test
1416

17+
.PHONY: test-op
18+
test-op:
19+
cargo test --features optimism
20+
21+
.PHONY: clean
1522
clean:
1623
cargo clean
1724

25+
.PHONY: fmt
1826
fmt:
1927
cargo fmt
2028

29+
.PHONY: fmt-check
2130
fmt-check:
2231
cargo fmt --all --check
2332

33+
.PHONY: clippy
2434
clippy:
25-
cargo clippy --all -- -D warnings
35+
cargo clippy --all --all-features -- -D warnings
2636

37+
.PHONY: taplo
2738
taplo:
2839
taplo format
2940

41+
.PHONY: taplo-check
3042
taplo-check:
3143
taplo format --check
3244

45+
.PHONY: deny-check
3346
deny-check:
3447
cargo deny --all-features check
3548

@@ -38,5 +51,6 @@ pre-release:
3851
make fmt
3952
make clippy
4053
make test
54+
make test-op
4155
make taplo-check
4256
make deny-check

examples/evm_call.rs

+40-19
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,72 @@
1+
#[cfg(not(feature = "optimism"))]
12
use alloy_eips::BlockId;
3+
#[cfg(not(feature = "optimism"))]
24
use alloy_primitives::utils::parse_units;
5+
#[cfg(not(feature = "optimism"))]
36
use alloy_primitives::{address, Bytes, B256, U256};
7+
#[cfg(not(feature = "optimism"))]
48
use alloy_provider::ProviderBuilder;
9+
#[cfg(not(feature = "optimism"))]
510
use alloy_reth_provider::AlloyRethProvider;
11+
#[cfg(not(feature = "optimism"))]
12+
use reth_ethereum_primitives::EthPrimitives;
13+
#[cfg(not(feature = "optimism"))]
614
use reth_provider::StateProviderFactory;
15+
#[cfg(not(feature = "optimism"))]
716
use reth_revm::database::StateProviderDatabase;
8-
use revm::primitives::{BlockEnv, Env, ResultAndState, SpecId, TransactTo, TxEnv};
9-
use revm::Evm;
17+
#[cfg(not(feature = "optimism"))]
18+
use reth_revm::{ExecuteEvm, MainBuilder, MainContext};
19+
#[cfg(not(feature = "optimism"))]
20+
use revm_context::result::ResultAndState;
21+
#[cfg(not(feature = "optimism"))]
22+
use revm_context::{BlockEnv, Context, Evm, TransactTo, TxEnv};
23+
#[cfg(not(feature = "optimism"))]
1024
use std::str::FromStr;
1125

26+
#[cfg(feature = "optimism")]
27+
fn main() {
28+
println!("Optimism not implemented");
29+
}
30+
31+
#[cfg(not(feature = "optimism"))]
1232
#[tokio::main]
1333
async fn main() -> eyre::Result<()> {
14-
let provider = ProviderBuilder::new().on_http("https://eth.merkle.io".parse()?);
15-
let db_provider = AlloyRethProvider::new(provider);
34+
let provider = ProviderBuilder::default().on_http("https://eth.merkle.io".parse()?);
35+
let db_provider = AlloyRethProvider::new(provider, EthPrimitives::default());
1636
// Top of block state previous block
1737
let state_provider = db_provider.state_by_block_id(BlockId::number(16148322))?;
1838
let state_db = StateProviderDatabase::new(state_provider);
1939

20-
let mut env = Env {
21-
block: BlockEnv {
40+
let ctx = Context::mainnet()
41+
.with_db(state_db)
42+
.with_block(BlockEnv {
2243
// next block
23-
number: U256::from(16148323),
24-
timestamp: U256::from(1670565947),
25-
basefee: parse_units("176.658583385", "gwei")?.get_absolute(),
44+
number: 16148323,
45+
timestamp: 1670565947,
46+
basefee: 176_658583385,
2647
..BlockEnv::default()
27-
},
28-
..Env::default()
29-
};
48+
})
49+
.build_mainnet();
50+
3051
// Simulate 0x2bb4f9fd58b3cd99591737eca784d0cf281034661bbdc509b58cf6a499d3d998
31-
env.tx = TxEnv {
52+
let tx = TxEnv {
3253
caller: address!("0x80d3aB7f834f786CAb110Bea9E8A96d45B2dc9C2"),
3354
gas_limit: 55_984,
34-
gas_price: parse_units("241.400106299", "gwei")?.get_absolute(),
35-
gas_priority_fee: Some(parse_units("1.5", "gwei")?.get_absolute()),
36-
transact_to: TransactTo::Call(address!("0x8686525d6627A25C68De82c228448f43c97999F2")),
55+
gas_price: 241_400106299,
56+
gas_priority_fee: Some(parse_units("1.5", "gwei")?.get_absolute().to::<u128>()),
57+
kind: TransactTo::Call(address!("0x8686525d6627A25C68De82c228448f43c97999F2")),
3758
data: Bytes::from_str(
3859
"0x095ea7b3\
3960
00000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45\
4061
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
4162
)?,
42-
nonce: Some(401),
63+
nonce: 401,
4364
chain_id: Some(1),
4465
..TxEnv::default()
4566
};
4667

47-
let mut evm = Evm::builder().with_spec_id(SpecId::SHANGHAI).with_ref_db(state_db).with_env(Box::new(env)).build();
48-
let ResultAndState { result, state } = evm.transact()?;
68+
let mut evm = Evm::new(ctx);
69+
let ResultAndState { result, state } = evm.transact(tx)?;
4970

5071
println!("Success: {}", result.is_success());
5172
let slot = state

src/alloy_db/alloy_db_fork.rs

+51-25
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,41 @@
1-
// FORK FROM: https://github.com/bluealloy/revm/blob/4e24be4/crates/database/src/alloydb.rs
1+
// FORK FROM: https://github.com/bluealloy/revm/blob/389be74/crates/database/src/alloydb.rs
22

33
use crate::alloy_db::async_db::DatabaseAsyncRef;
44
pub use alloy_eips::BlockId;
5-
use alloy_network::primitives::HeaderResponse;
65
use alloy_primitives::{Address, B256, U256};
7-
use alloy_provider::network::primitives::BlockTransactionsKind;
8-
use alloy_provider::network::BlockResponse;
9-
use alloy_provider::{Network, Provider};
6+
use alloy_provider::{
7+
network::{
8+
primitives::{BlockTransactionsKind, HeaderResponse},
9+
BlockResponse,
10+
},
11+
Network, Provider,
12+
};
1013
use alloy_transport::TransportError;
11-
use revm::primitives::{AccountInfo, Bytecode};
14+
use core::error::Error;
15+
use revm_database::DBErrorMarker;
16+
use revm_state::{AccountInfo, Bytecode};
17+
use std::fmt::Display;
1218

13-
/// An alloy-powered REVM [revm::Database].
19+
#[derive(Debug)]
20+
pub struct DBTransportError(pub TransportError);
21+
22+
impl DBErrorMarker for DBTransportError {}
23+
24+
impl Display for DBTransportError {
25+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
26+
write!(f, "Transport error: {}", self.0)
27+
}
28+
}
29+
30+
impl Error for DBTransportError {}
31+
32+
impl From<TransportError> for DBTransportError {
33+
fn from(e: TransportError) -> Self {
34+
Self(e)
35+
}
36+
}
37+
38+
/// An alloy-powered REVM [Database][database_interface::Database].
1439
///
1540
/// When accessing the database, it'll use the given provider to fetch the corresponding account's data.
1641
#[derive(Debug)]
@@ -19,23 +44,23 @@ pub struct AlloyDBFork<N: Network, P: Provider<N>> {
1944
provider: P,
2045
/// The block number on which the queries will be based on.
2146
block_number: BlockId,
22-
_n: std::marker::PhantomData<N>,
47+
_marker: core::marker::PhantomData<fn() -> N>,
2348
}
2449

2550
impl<N: Network, P: Provider<N>> AlloyDBFork<N, P> {
26-
/// Create a new AlloyDB instance, with a [Provider] and a block.
51+
/// Creates a new AlloyDBFork instance, with a [Provider] and a block.
2752
pub fn new(provider: P, block_number: BlockId) -> Self {
28-
Self { provider, block_number, _n: std::marker::PhantomData }
53+
Self { provider, block_number, _marker: core::marker::PhantomData }
2954
}
3055

31-
/// Set the block number on which the queries will be based on.
56+
/// Sets the block number on which the queries will be based on.
3257
pub fn set_block_number(&mut self, block_number: BlockId) {
3358
self.block_number = block_number;
3459
}
3560
}
3661

3762
impl<N: Network, P: Provider<N>> DatabaseAsyncRef for AlloyDBFork<N, P> {
38-
type Error = TransportError;
63+
type Error = DBTransportError;
3964

4065
async fn basic_async_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
4166
let nonce = self.provider.get_transaction_count(address).block_id(self.block_number);
@@ -56,7 +81,8 @@ impl<N: Network, P: Provider<N>> DatabaseAsyncRef for AlloyDBFork<N, P> {
5681
let block = self
5782
.provider
5883
// SAFETY: We know number <= u64::MAX, so we can safely convert it to u64
59-
.get_block_by_number(number.into(), BlockTransactionsKind::Hashes)
84+
.get_block_by_number(number.into())
85+
.kind(BlockTransactionsKind::Hashes)
6086
.await?;
6187
// SAFETY: If the number is given, the block is supposed to be finalized, so unwrapping is safe.
6288
Ok(B256::new(*block.unwrap().header().hash()))
@@ -68,28 +94,28 @@ impl<N: Network, P: Provider<N>> DatabaseAsyncRef for AlloyDBFork<N, P> {
6894
}
6995

7096
async fn storage_async_ref(&self, address: Address, index: U256) -> Result<U256, Self::Error> {
71-
self.provider.get_storage_at(address, index).block_id(self.block_number).await
97+
Ok(self.provider.get_storage_at(address, index).block_id(self.block_number).await?)
7298
}
7399
}
74100

75101
#[cfg(test)]
76102
mod tests {
77103
use super::*;
78-
use crate::alloy_db::async_db::WrapDatabaseAsync;
79-
use alloy_primitives::address;
80-
use alloy_primitives::ruint::__private::ruint_macro::uint;
104+
use crate::alloy_db::WrapDatabaseAsync;
81105
use alloy_provider::ProviderBuilder;
82-
use revm::DatabaseRef;
106+
use revm_database::DatabaseRef;
83107

84-
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
85-
async fn can_get_basic() {
86-
let client = ProviderBuilder::new().on_http("https://eth.merkle.io".parse().unwrap());
87-
let alloydb = AlloyDBFork::new(client, BlockId::number(16148323));
108+
#[test]
109+
#[ignore = "flaky RPC"]
110+
fn can_get_basic() {
111+
let client = ProviderBuilder::new().on_http("https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27".parse().unwrap());
112+
let alloydb = AlloyDBFork::new(client, BlockId::from(16148323));
88113
let wrapped_alloydb = WrapDatabaseAsync::new(alloydb).unwrap();
89114

90-
let acc_info = wrapped_alloydb.basic_ref(address!("220866b1a2219f40e72f5c628b65d54268ca3a9d")).unwrap().unwrap();
115+
// ETH/USDT pair on Uniswap V2
116+
let address: Address = "0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852".parse().unwrap();
117+
118+
let acc_info = wrapped_alloydb.basic_ref(address).unwrap().unwrap();
91119
assert!(acc_info.exists());
92-
assert_eq!(acc_info.nonce, 1);
93-
assert_eq!(acc_info.balance, uint!(250001010477701567100010_U256));
94120
}
95121
}

0 commit comments

Comments
 (0)