Skip to content

Commit c21d269

Browse files
authored
feat(primitives): get_deposit_tx_parts helper (#12808)
Converts `OtherFields` to `DepositTransactionParts`, produces error with missing fields
1 parent 52b4dd1 commit c21d269

File tree

3 files changed

+47
-49
lines changed

3 files changed

+47
-49
lines changed

crates/anvil/src/eth/backend/mem/mod.rs

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,12 @@ use foundry_evm::{
107107
},
108108
utils::{get_blob_base_fee_update_fraction, get_blob_base_fee_update_fraction_by_spec_id},
109109
};
110-
use foundry_primitives::{FoundryReceiptEnvelope, FoundryTransactionRequest, FoundryTxEnvelope};
110+
use foundry_primitives::{
111+
FoundryReceiptEnvelope, FoundryTransactionRequest, FoundryTxEnvelope, get_deposit_tx_parts,
112+
};
111113
use futures::channel::mpsc::{UnboundedSender, unbounded};
112114
use op_alloy_consensus::DEPOSIT_TX_TYPE_ID;
113-
use op_revm::{
114-
OpContext, OpHaltReason, OpTransaction, transaction::deposit::DepositTransactionParts,
115-
};
115+
use op_revm::{OpContext, OpHaltReason, OpTransaction};
116116
use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard};
117117
use revm::{
118118
DatabaseCommit, Inspector,
@@ -1555,7 +1555,6 @@ impl Backend {
15551555
nonce,
15561556
sidecar: _,
15571557
chain_id,
1558-
transaction_type,
15591558
.. // Rest of the gas fees related fields are taken from `fee_details`
15601559
},
15611560
other,
@@ -1632,20 +1631,7 @@ impl Backend {
16321631
}
16331632

16341633
// Deposit transaction?
1635-
if transaction_type == Some(DEPOSIT_TX_TYPE_ID)
1636-
&& let (Some(source_hash), Some(mint), Some(is_system_transaction)) = (
1637-
other.get_deserialized::<B256>("sourceHash").transpose().ok().flatten(),
1638-
other
1639-
.get_deserialized::<U256>("mint")
1640-
.transpose()
1641-
.ok()
1642-
.flatten()
1643-
.map(|m| m.to::<u128>()),
1644-
other.get_deserialized::<bool>("isSystemTx").transpose().ok().flatten(),
1645-
)
1646-
{
1647-
let deposit =
1648-
DepositTransactionParts { source_hash, mint: Some(mint), is_system_transaction };
1634+
if let Ok(deposit) = get_deposit_tx_parts(&other) {
16491635
env.tx.deposit = deposit;
16501636
}
16511637

crates/primitives/src/transaction/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ mod request;
44

55
pub use envelope::{FoundryTxEnvelope, FoundryTxType, FoundryTypedTx};
66
pub use receipt::FoundryReceiptEnvelope;
7-
pub use request::FoundryTransactionRequest;
7+
pub use request::{FoundryTransactionRequest, get_deposit_tx_parts};

crates/primitives/src/transaction/request.rs

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use alloy_rpc_types::{AccessList, TransactionInputKind, TransactionRequest};
77
use alloy_serde::{OtherFields, WithOtherFields};
88
use derive_more::{AsMut, AsRef, From, Into};
99
use op_alloy_consensus::{DEPOSIT_TX_TYPE_ID, TxDeposit};
10+
use op_revm::transaction::deposit::DepositTransactionParts;
1011
use serde::{Deserialize, Serialize};
1112

1213
use super::{FoundryTxEnvelope, FoundryTxType, FoundryTypedTx};
@@ -51,11 +52,6 @@ impl FoundryTransactionRequest {
5152
self.as_ref().transaction_type == Some(DEPOSIT_TX_TYPE_ID)
5253
}
5354

54-
/// Helper to access [`FoundryTransactionRequest`] custom fields
55-
pub fn get_other_field<T: serde::de::DeserializeOwned>(&self, key: &str) -> Option<T> {
56-
self.as_ref().other.get_deserialized::<T>(key).transpose().ok().flatten()
57-
}
58-
5955
/// Returns the minimal transaction type this request can be converted into based on the fields
6056
/// that are set. See [`TransactionRequest::preferred_type`].
6157
pub fn preferred_type(&self) -> FoundryTxType {
@@ -85,17 +81,7 @@ impl FoundryTransactionRequest {
8581
/// Check if all necessary keys are present to build a Deposit transaction, returning a list of
8682
/// keys that are missing.
8783
pub fn complete_deposit(&self) -> Result<(), Vec<&'static str>> {
88-
let mut missing = Vec::new();
89-
if self.get_other_field::<B256>("sourceHash").is_none() {
90-
missing.push("sourceHash");
91-
}
92-
if self.get_other_field::<u128>("mint").is_none() {
93-
missing.push("mint");
94-
}
95-
if self.get_other_field::<bool>("isSystemTx").is_none() {
96-
missing.push("isSystemTx");
97-
}
98-
if missing.is_empty() { Ok(()) } else { Err(missing) }
84+
get_deposit_tx_parts(&self.as_ref().other).map(|_| ())
9985
}
10086

10187
/// Return the tx type this request can be built as. Computed by checking
@@ -141,19 +127,15 @@ impl FoundryTransactionRequest {
141127
/// types.
142128
pub fn build_typed_tx(self) -> Result<FoundryTypedTx, Self> {
143129
// Handle deposit transactions
144-
if let (Some(source_hash), Some(mint), Some(is_system_transaction)) = (
145-
self.get_other_field::<B256>("sourceHash"),
146-
self.get_other_field::<U256>("mint").map(|m| m.to::<u128>()),
147-
self.get_other_field::<bool>("isSystemTx"),
148-
) {
130+
if let Ok(deposit_tx_parts) = get_deposit_tx_parts(&self.as_ref().other) {
149131
Ok(FoundryTypedTx::Deposit(TxDeposit {
150132
from: self.from().unwrap_or_default(),
151-
source_hash,
133+
source_hash: deposit_tx_parts.source_hash,
152134
to: self.kind().unwrap_or_default(),
153-
mint,
135+
mint: deposit_tx_parts.mint.unwrap_or_default(),
154136
value: self.value().unwrap_or_default(),
155137
gas_limit: self.gas_limit().unwrap_or_default(),
156-
is_system_transaction,
138+
is_system_transaction: deposit_tx_parts.is_system_transaction,
157139
input: self.input().cloned().unwrap_or_default(),
158140
}))
159141
} else if self.as_ref().has_eip4844_fields() && self.as_ref().blob_sidecar().is_none() {
@@ -336,11 +318,7 @@ impl TransactionBuilder<FoundryNetwork> for FoundryTransactionRequest {
336318
}
337319

338320
fn can_build(&self) -> bool {
339-
let deposit = self.get_other_field::<B256>("sourceHash").is_some()
340-
&& self.get_other_field::<u128>("mint").is_some()
341-
&& self.get_other_field::<bool>("isSystemTx").is_some();
342-
343-
self.as_ref().can_build() || deposit
321+
self.as_ref().can_build() || get_deposit_tx_parts(&self.as_ref().other).is_ok()
344322
}
345323

346324
fn output_tx_type(&self) -> FoundryTxType {
@@ -406,3 +384,37 @@ impl TransactionBuilder<FoundryNetwork> for FoundryTransactionRequest {
406384
Ok(wallet.sign_request(self).await?)
407385
}
408386
}
387+
388+
/// Converts `OtherFields` to `DepositTransactionParts`, produces error with missing fields
389+
pub fn get_deposit_tx_parts(
390+
other: &OtherFields,
391+
) -> Result<DepositTransactionParts, Vec<&'static str>> {
392+
let mut missing = Vec::new();
393+
let source_hash =
394+
other.get_deserialized::<B256>("sourceHash").transpose().ok().flatten().unwrap_or_else(
395+
|| {
396+
missing.push("sourceHash");
397+
Default::default()
398+
},
399+
);
400+
let mint = other
401+
.get_deserialized::<U256>("mint")
402+
.transpose()
403+
.unwrap_or_else(|_| {
404+
missing.push("mint");
405+
Default::default()
406+
})
407+
.map(|value| value.to::<u128>());
408+
let is_system_transaction =
409+
other.get_deserialized::<bool>("isSystemTx").transpose().ok().flatten().unwrap_or_else(
410+
|| {
411+
missing.push("isSystemTx");
412+
Default::default()
413+
},
414+
);
415+
if missing.is_empty() {
416+
Ok(DepositTransactionParts { source_hash, mint, is_system_transaction })
417+
} else {
418+
Err(missing)
419+
}
420+
}

0 commit comments

Comments
 (0)