Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.

Commit 2ff7997

Browse files
committed
add eip1559/2930 support to StateTest
1 parent 6457d71 commit 2ff7997

File tree

1 file changed

+113
-2
lines changed

1 file changed

+113
-2
lines changed

testool/src/statetest/spec.rs

+113-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
use anyhow::{anyhow, bail, Context};
2-
use eth_types::{geth_types::Account, Address, Bytes, Word, H256, U256, U64};
3-
use ethers_core::{k256::ecdsa::SigningKey, utils::secret_key_to_address};
2+
use eth_types::{
3+
geth_types::{Account, TxType},
4+
Address, Bytes, Word, H256, U256, U64,
5+
};
6+
use ethers_core::{
7+
k256::ecdsa::SigningKey,
8+
types::{
9+
transaction::{eip2718::TypedTransaction, eip2930::AccessList},
10+
Eip1559TransactionRequest, TransactionRequest,
11+
},
12+
utils::secret_key_to_address,
13+
};
414
use std::{
515
collections::{BTreeMap, HashMap},
616
str::FromStr,
@@ -9,6 +19,8 @@ use std::{
919
/// <https://github.com/ethereum/tests/pull/857> "set default gasPrice to 10"
1020
pub const DEFAULT_BASE_FEE: u32 = 10;
1121

22+
const ETH_CHAIN_ID: u64 = 1;
23+
1224
#[derive(PartialEq, Eq, Debug, Clone)]
1325
pub struct Env {
1426
pub current_base_fee: U256,
@@ -53,10 +65,13 @@ pub struct StateTest {
5365
pub from: Address,
5466
pub to: Option<Address>,
5567
pub gas_limit: u64,
68+
pub max_priority_fee_per_gas: Option<U256>,
69+
pub max_fee_per_gas: Option<U256>,
5670
pub gas_price: U256,
5771
pub nonce: u64,
5872
pub value: U256,
5973
pub data: Bytes,
74+
pub access_list: Option<AccessList>,
6075
pub pre: BTreeMap<Address, Account>,
6176
pub result: StateTestResult,
6277
pub exception: bool,
@@ -108,10 +123,19 @@ impl std::fmt::Display for StateTest {
108123
table.add_row(row!["from", format!("{:?}", self.from)]);
109124
table.add_row(row!["to", format!("{:?}", self.to)]);
110125
table.add_row(row!["gas_limit", format!("{}", self.gas_limit)]);
126+
table.add_row(row![
127+
"max_priority_fee_per_gas",
128+
format!("{:?}", self.max_priority_fee_per_gas)
129+
]);
130+
table.add_row(row![
131+
"max_fee_per_gas",
132+
format!("{:?}", self.max_fee_per_gas)
133+
]);
111134
table.add_row(row!["gas_price", format!("{}", self.gas_price)]);
112135
table.add_row(row!["nonce", format!("{}", self.nonce)]);
113136
table.add_row(row!["value", format!("{}", self.value)]);
114137
table.add_row(row!["data", format(&hex::encode(&self.data), "")]);
138+
table.add_row(row!["access_list", format!("{:?}", self.access_list)]);
115139
table.add_row(row!["exception", self.exception]);
116140

117141
let mut addrs: Vec<_> = self.pre.keys().collect();
@@ -273,15 +297,102 @@ impl StateTest {
273297
from,
274298
to,
275299
gas_limit,
300+
max_priority_fee_per_gas: None,
301+
max_fee_per_gas: None,
276302
gas_price: U256::one(),
277303
nonce: 0,
278304
value,
279305
data: data.into(),
306+
access_list: None,
280307
pre,
281308
result: HashMap::new(),
282309
exception: false,
283310
};
284311

285312
Ok(state_test)
286313
}
314+
315+
/// Parse transaction type.
316+
pub fn tx_type(&self) -> TxType {
317+
if self.max_priority_fee_per_gas.is_some() {
318+
// For EIP-1559, both maxPriorityFeePerGas and maxFeePerGas must
319+
// exist, and accessList should exist but may be empty.
320+
assert!(self.max_fee_per_gas.is_some());
321+
assert!(self.access_list.is_some());
322+
323+
TxType::Eip1559
324+
} else if self.access_list.is_some() {
325+
TxType::Eip2930
326+
} else {
327+
// Set transaction type to EIP-155 as default.
328+
TxType::Eip155
329+
}
330+
}
331+
332+
/// Normalize the signature back to 0/1.
333+
pub fn normalize_sig_v(&self, v: u64) -> u64 {
334+
match self.tx_type() {
335+
TxType::Eip1559 | TxType::Eip2930 => {
336+
// <https://github.com/gakonst/ethers-rs/blob/8421cfdbb4f26be3989bd11e525f8768d4323bfe/ethers-core/src/types/transaction/mod.rs#L40>
337+
if v > 1 {
338+
v - ETH_CHAIN_ID * 2 - 35
339+
} else {
340+
v
341+
}
342+
}
343+
_ => v,
344+
}
345+
}
346+
347+
/// Build a transaction from this test case.
348+
pub fn build_tx(&self) -> TypedTransaction {
349+
match self.tx_type() {
350+
TxType::Eip1559 => self.build_eip1559_tx(),
351+
TxType::Eip2930 => self.build_eip2930_tx(),
352+
_ => self.build_normal_tx_request().into(),
353+
}
354+
}
355+
356+
fn build_eip1559_tx(&self) -> TypedTransaction {
357+
let mut request = Eip1559TransactionRequest::new()
358+
.chain_id(ETH_CHAIN_ID)
359+
.from(self.from)
360+
.nonce(self.nonce)
361+
.value(self.value)
362+
.data(self.data.clone())
363+
.gas(self.gas_limit)
364+
.access_list(self.access_list.clone().unwrap())
365+
.max_priority_fee_per_gas(self.max_priority_fee_per_gas.unwrap())
366+
.max_fee_per_gas(self.max_fee_per_gas.unwrap());
367+
368+
if let Some(to) = self.to {
369+
request = request.to(to);
370+
}
371+
372+
request.into()
373+
}
374+
375+
fn build_eip2930_tx(&self) -> TypedTransaction {
376+
let request = self.build_normal_tx_request();
377+
request
378+
.with_access_list(self.access_list.clone().unwrap())
379+
.into()
380+
}
381+
382+
fn build_normal_tx_request(&self) -> TransactionRequest {
383+
let mut request = TransactionRequest::new()
384+
.chain_id(ETH_CHAIN_ID)
385+
.from(self.from)
386+
.nonce(self.nonce)
387+
.value(self.value)
388+
.data(self.data.clone())
389+
.gas(self.gas_limit)
390+
.gas_price(self.gas_price);
391+
392+
if let Some(to) = self.to {
393+
request = request.to(to);
394+
}
395+
396+
request
397+
}
287398
}

0 commit comments

Comments
 (0)