Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix deposit tx nonce handling
  • Loading branch information
mdehoog authored and anikaraghu committed Nov 21, 2023
commit 68718e1f9eb04671fa283902ffe9f6e0dea3c2c0
4 changes: 4 additions & 0 deletions crates/anvil/core/src/eth/receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ impl Decodable for TypedReceipt {
return rlp::decode(s).map(TypedReceipt::EIP1559)
}

if first == 0x7E {
return rlp::decode(s).map(TypedReceipt::OpDeposit)
}

Err(DecoderError::Custom("unknown receipt type"))
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/anvil/core/src/eth/transaction/ethers_compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ fn to_ethers_transaction_with_hash_and_sender(
},
TypedTransaction::OpDeposit(t) => EthersTransaction {
hash,
nonce: t.nonce(),
nonce: t.nonce,
block_hash: None,
block_number: None,
transaction_index: None,
Expand Down
45 changes: 18 additions & 27 deletions crates/anvil/core/src/eth/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ pub struct EthTransactionRequest {
impl EthTransactionRequest {
/// Converts the request into a [TypedTransactionRequest]
pub fn into_typed_request(self) -> Option<TypedTransactionRequest> {
println!("into_typed_request({0})", self.from?.to_string());
let EthTransactionRequest {
from,
to,
Expand Down Expand Up @@ -156,7 +155,6 @@ impl EthTransactionRequest {
}
// op-stack deposit
(Some(126), None, None, None, None) => {
println!("into_typed_request()");
Some(TypedTransactionRequest::OpDeposit(OpDepositTransactionRequest {
source_hash: source_hash.unwrap_or_default(),
from: from.unwrap_or_default(),
Expand Down Expand Up @@ -716,7 +714,7 @@ impl TypedTransaction {
TypedTransaction::OpDeposit(t) => TransactionEssentials {
kind: t.kind,
input: t.input.clone(),
nonce: t.nonce(),
nonce: t.nonce,
gas_limit: t.gas_limit,
gas_price: Some(U256::from(0)),
max_fee_per_gas: None,
Expand All @@ -728,7 +726,7 @@ impl TypedTransaction {
}
}

pub fn nonce(&self) -> U256 {
pub fn nonce(&self) -> &U256 {
match self {
TypedTransaction::Legacy(t) => t.nonce(),
TypedTransaction::EIP2930(t) => t.nonce(),
Expand Down Expand Up @@ -834,7 +832,7 @@ impl TypedTransaction {
Signature { r, s, v: v.into() }
}
TypedTransaction::OpDeposit(_) => {
Signature { r: U256::from(0), s: U256::from(0), v: 0 }
Signature { r: U256::zero(), s: U256::zero(), v: 0 }
},
}
}
Expand Down Expand Up @@ -1003,8 +1001,8 @@ pub struct LegacyTransaction {
}

impl LegacyTransaction {
pub fn nonce(&self) -> U256 {
self.nonce
pub fn nonce(&self) -> &U256 {
&self.nonce
}

pub fn hash(&self) -> H256 {
Expand Down Expand Up @@ -1090,8 +1088,8 @@ pub struct EIP2930Transaction {
}

impl EIP2930Transaction {
pub fn nonce(&self) -> U256 {
self.nonce
pub fn nonce(&self) -> &U256 {
&self.nonce
}

pub fn hash(&self) -> H256 {
Expand Down Expand Up @@ -1179,8 +1177,8 @@ pub struct EIP1559Transaction {
}

impl EIP1559Transaction {
pub fn nonce(&self) -> U256 {
self.nonce
pub fn nonce(&self) -> &U256 {
&self.nonce
}

pub fn hash(&self) -> H256 {
Expand Down Expand Up @@ -1255,6 +1253,7 @@ impl Decodable for EIP1559Transaction {
#[cfg_attr(feature = "fastrlp", derive(open_fastrlp::RlpEncodable, open_fastrlp::RlpDecodable))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct OpDepositTransaction {
pub nonce: U256,
pub source_hash: H256,
pub from: Address,
pub kind: TransactionKind,
Expand All @@ -1266,8 +1265,8 @@ pub struct OpDepositTransaction {
}

impl OpDepositTransaction {
pub fn nonce(&self) -> U256 {
U256::from(0)
pub fn nonce(&self) -> &U256 {
&self.nonce
}

pub fn hash(&self) -> H256 {
Expand All @@ -1282,16 +1281,6 @@ impl OpDepositTransaction {
pub fn chain_id(&self) -> Option<u64> {
None
}

// /// See <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md>
// /// > If you do, then the v of the signature MUST be set to {0,1} + CHAIN_ID * 2 + 35 where
// /// > {0,1} is the parity of the y value of the curve point for which r is the x-value in the
// /// > secp256k1 signing process.
// pub fn meets_eip155(&self, chain_id: u64) -> bool {
// let double_chain_id = chain_id.saturating_mul(2);
// let v = self.signature.v;
// v == double_chain_id + 35 || v == double_chain_id + 36
// }
}

impl Encodable for OpDepositTransaction {
Expand Down Expand Up @@ -1323,6 +1312,7 @@ impl Decodable for OpDepositTransaction {
gas_limit: rlp.val_at(5)?,
is_system_tx: rlp.val_at(6)?,
input: rlp.val_at::<Vec<u8>>(7)?.into(),
nonce: U256::from(0),
})
}
}
Expand Down Expand Up @@ -1374,8 +1364,8 @@ impl PendingTransaction {
Self { hash, transaction, sender }
}

pub fn nonce(&self) -> U256 {
self.transaction.nonce()
pub fn nonce(&self) -> &U256 {
&self.transaction.nonce()
}

pub fn hash(&self) -> &TxHash {
Expand Down Expand Up @@ -1470,13 +1460,13 @@ impl PendingTransaction {
}
TypedTransaction::OpDeposit(tx) => {
let chain_id = tx.chain_id();
let OpDepositTransaction { source_hash, gas_limit, value, kind, mint, input, is_system_tx, .. } = tx;
let OpDepositTransaction { nonce, source_hash, gas_limit, value, kind, mint, input, is_system_tx, .. } = tx;
TxEnv {
caller: caller.to_alloy(),
transact_to: transact_to(kind),
data: alloy_primitives::Bytes(input.0.clone()),
chain_id,
nonce: Some(tx.nonce().as_u64()),
nonce: Some(nonce.as_u64()),
value: (*value).to_alloy(),
gas_price: 0.to_alloy(),
gas_priority_fee: None,
Expand Down Expand Up @@ -1508,6 +1498,7 @@ pub struct TransactionInfo {
pub traces: CallTraceArena,
pub exit: InstructionResult,
pub out: Option<Bytes>,
pub nonce: u64,
}

// === impl TransactionInfo ===
Expand Down
2 changes: 1 addition & 1 deletion crates/anvil/src/eth/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,7 @@ impl EthApi {

let on_chain_nonce = self.backend.current_nonce(*pending_transaction.sender()).await?;
let from = *pending_transaction.sender();
let nonce = pending_transaction.transaction.nonce();
let nonce = *pending_transaction.transaction.nonce();
let requires = required_marker(nonce, on_chain_nonce, from);

let priority = self.transaction_priority(&pending_transaction.transaction);
Expand Down
5 changes: 5 additions & 0 deletions crates/anvil/src/eth/backend/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub struct ExecutedTransaction {
gas_used: u64,
logs: Vec<Log>,
traces: Vec<CallTraceNode>,
nonce: u64,
}

// == impl ExecutedTransaction ==
Expand Down Expand Up @@ -177,6 +178,7 @@ impl<'a, DB: Db + ?Sized, Validator: TransactionValidator> TransactionExecutor<'
Some(Output::Create(b, _)) => Some(ethers::types::Bytes(b.0)),
_ => None,
},
nonce: tx.nonce,
};

transaction_infos.push(info);
Expand Down Expand Up @@ -255,6 +257,8 @@ impl<'a, 'b, DB: Db + ?Sized, Validator: TransactionValidator> Iterator
return Some(TransactionExecutionOutcome::Invalid(transaction, err))
}

let nonce = account.nonce;

let mut evm = revm::EVM::new();
evm.env = env;
evm.database(&mut self.db);
Expand Down Expand Up @@ -318,6 +322,7 @@ impl<'a, 'b, DB: Db + ?Sized, Validator: TransactionValidator> Iterator
gas_used,
logs: logs.unwrap_or_default().into_iter().map(Into::into).collect(),
traces: inspector.tracer.unwrap_or_default().traces.arena,
nonce,
};

Some(TransactionExecutionOutcome::Executed(tx))
Expand Down
21 changes: 12 additions & 9 deletions crates/anvil/src/eth/backend/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1929,6 +1929,11 @@ impl Backend {
TypedTransaction::OpDeposit(_) => U256::from(0),
};

let mut deposit_nonce: Option<u64> = None;
if transaction_type.unwrap_or_default() == 0x7E {
deposit_nonce = Some(info.nonce);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deposit_nonce = transaction_type.and_then(|ty| (x == 0x7E).then_some(info.nonce))


let inner = TransactionReceipt {
transaction_hash: info.transaction_hash,
transaction_index: info.transaction_index.into(),
Expand Down Expand Up @@ -1970,7 +1975,7 @@ impl Backend {
logs_bloom,
transaction_type: transaction_type.map(Into::into),
effective_gas_price: Some(effective_gas_price),
deposit_nonce: None,
deposit_nonce,
l1_fee: None,
l1_fee_scalar: None,
l1_gas_price: None,
Expand Down Expand Up @@ -2222,12 +2227,6 @@ impl TransactionValidator for Backend {
) -> Result<(), InvalidTransactionError> {
let tx = &pending.transaction;

// let is_deposit_tx = match &pending.transaction.transaction {
// TypedTransaction::OpDeposit(_) => true,
// default => false,
// };
let is_deposit_tx = matches!(&pending.transaction.transaction, TypedTransaction::OpDeposit(_));

if let Some(tx_chain_id) = tx.chain_id() {
let chain_id = self.chain_id();
if chain_id != tx_chain_id {
Expand Down Expand Up @@ -2259,9 +2258,10 @@ impl TransactionValidator for Backend {
}

// check nonce
let is_deposit_tx = matches!(&pending.transaction.transaction, TypedTransaction::OpDeposit(_));
let nonce: u64 =
(tx.nonce()).try_into().map_err(|_| InvalidTransactionError::NonceMaxValue)?;
if nonce < account.nonce {
(*tx.nonce()).try_into().map_err(|_| InvalidTransactionError::NonceMaxValue)?;
if nonce < account.nonce && !is_deposit_tx {
warn!(target: "backend", "[{:?}] nonce too low", tx.hash());
return Err(InvalidTransactionError::NonceTooLow)
}
Expand Down Expand Up @@ -2322,6 +2322,9 @@ pub fn transaction_build(
base_fee: Option<U256>,
) -> Transaction {
let mut transaction: Transaction = eth_transaction.clone().into();
if info.is_some() && transaction.transaction_type.unwrap_or(U64::zero()).as_u64() == 0x7E {
transaction.nonce = U256::from(info.as_ref().unwrap().nonce);
}

if eth_transaction.is_dynamic_fee() {
if block.is_none() && info.is_none() {
Expand Down
3 changes: 2 additions & 1 deletion crates/anvil/src/eth/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use ethers::{
transaction::{
eip2718::TypedTransaction as EthersTypedTransactionRequest, eip712::TypedData,
},
Signature, H256,
Signature, H256, U256,
},
};
use std::collections::HashMap;
Expand Down Expand Up @@ -208,6 +208,7 @@ pub fn build_typed_transaction(
source_hash,
mint,
is_system_tx,
nonce: U256::zero(),
})
}
};
Expand Down