From 21023f435e463ba9386023e87d8f1f3c2ccb96ab Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Thu, 4 Apr 2024 23:36:24 -0400 Subject: [PATCH] Numeric type audit: network, consensus, provider, rpc-types (#454) * num_type_audit: network, consensus, provider, rpc-types * `gas_limit` -> `u128` * `gas` -> `u128` * `gas_price` -> `u128` * `max_fee_per_blob_gas` -> `u128` * `transaction_type` -> `u8` * `max_fee_per_gas` -> `u128` * `max_priority_fee_per_gas` -> `u128` * Consequently, changed fn args and return values accordingly. * Satisfies clippy, tests will fail. * fix(rpc-type): transaction requests tests * fix(rpc-types): tests - transaction type * add u128_hex_or_decimal_opt serde * fix(providers): provider::tests * fix(providers): layers::gas::tests * fix: docs ci * fix(provider): estimate_gas should return u128 * add(serde): unit test for u128_hex_or_decimal_opt * fix(rpc-types, provider): use primitives in FeeHistory and its related methods * add u128_vec serde methods * ci nits * nit --- crates/consensus/src/transaction/eip1559.rs | 8 +- crates/consensus/src/transaction/eip2930.rs | 10 +- crates/consensus/src/transaction/eip4844.rs | 16 +- crates/consensus/src/transaction/envelope.rs | 2 +- crates/consensus/src/transaction/legacy.rs | 10 +- crates/consensus/src/transaction/mod.rs | 4 +- crates/consensus/src/transaction/typed.rs | 4 +- crates/contract/src/call.rs | 6 +- crates/network/src/any/builder.rs | 21 ++- crates/network/src/ethereum/builder.rs | 63 +++---- crates/network/src/transaction/builder.rs | 30 ++-- crates/provider/src/layers/gas.rs | 9 +- crates/provider/src/layers/nonce.rs | 12 +- crates/provider/src/layers/signer.rs | 4 +- crates/provider/src/provider.rs | 72 ++++---- crates/provider/src/utils.rs | 61 ++++--- crates/rpc-types/src/eth/fee.rs | 41 +++-- crates/rpc-types/src/eth/transaction/mod.rs | 109 ++++++++----- .../rpc-types/src/eth/transaction/receipt.rs | 1 - .../rpc-types/src/eth/transaction/request.rs | 28 ++-- .../rpc-types/src/eth/transaction/tx_type.rs | 6 - crates/serde/src/num.rs | 154 ++++++++++++++++++ crates/signer-trezor/src/signer.rs | 6 +- 23 files changed, 422 insertions(+), 255 deletions(-) diff --git a/crates/consensus/src/transaction/eip1559.rs b/crates/consensus/src/transaction/eip1559.rs index f3010c03ade..b9fbfe8c45b 100644 --- a/crates/consensus/src/transaction/eip1559.rs +++ b/crates/consensus/src/transaction/eip1559.rs @@ -20,8 +20,8 @@ pub struct TxEip1559 { /// this transaction. This is paid up-front, before any /// computation is done and may not be increased /// later; formally Tg. - #[cfg_attr(feature = "serde", serde(with = "alloy_serde::u64_hex_or_decimal"))] - pub gas_limit: u64, + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::u128_hex_or_decimal"))] + pub gas_limit: u128, /// A scalar value equal to the maximum /// amount of gas that should be used in executing /// this transaction. This is paid up-front, before any @@ -273,11 +273,11 @@ impl Transaction for TxEip1559 { self.nonce } - fn gas_limit(&self) -> u64 { + fn gas_limit(&self) -> u128 { self.gas_limit } - fn gas_price(&self) -> Option { + fn gas_price(&self) -> Option { None } } diff --git a/crates/consensus/src/transaction/eip2930.rs b/crates/consensus/src/transaction/eip2930.rs index e0ef9b252ac..cc377579c4f 100644 --- a/crates/consensus/src/transaction/eip2930.rs +++ b/crates/consensus/src/transaction/eip2930.rs @@ -29,8 +29,8 @@ pub struct TxEip2930 { /// this transaction. This is paid up-front, before any /// computation is done and may not be increased /// later; formally Tg. - #[cfg_attr(feature = "serde", serde(with = "alloy_serde::u64_hex_or_decimal"))] - pub gas_limit: u64, + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::u128_hex_or_decimal"))] + pub gas_limit: u128, /// The 160-bit address of the message call’s recipient or, for a contract creation /// transaction, ∅, used here to denote the only member of B0 ; formally Tt. #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "TxKind::is_create"))] @@ -237,12 +237,12 @@ impl Transaction for TxEip2930 { self.nonce } - fn gas_limit(&self) -> u64 { + fn gas_limit(&self) -> u128 { self.gas_limit } - fn gas_price(&self) -> Option { - Some(U256::from(self.gas_price)) + fn gas_price(&self) -> Option { + Some(self.gas_price) } } diff --git a/crates/consensus/src/transaction/eip4844.rs b/crates/consensus/src/transaction/eip4844.rs index 28e15ae32ca..b1946913eb8 100644 --- a/crates/consensus/src/transaction/eip4844.rs +++ b/crates/consensus/src/transaction/eip4844.rs @@ -232,14 +232,14 @@ impl Transaction for TxEip4844Variant { } } - fn gas_limit(&self) -> u64 { + fn gas_limit(&self) -> u128 { match self { TxEip4844Variant::TxEip4844(tx) => tx.gas_limit, TxEip4844Variant::TxEip4844WithSidecar(tx) => tx.tx().gas_limit, } } - fn gas_price(&self) -> Option { + fn gas_price(&self) -> Option { None } @@ -333,8 +333,8 @@ pub struct TxEip4844 { /// this transaction. This is paid up-front, before any /// computation is done and may not be increased /// later; formally Tg. - #[cfg_attr(feature = "serde", serde(with = "alloy_serde::u64_hex_or_decimal"))] - pub gas_limit: u64, + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::u128_hex_or_decimal"))] + pub gas_limit: u128, /// A scalar value equal to the maximum /// amount of gas that should be used in executing /// this transaction. This is paid up-front, before any @@ -716,11 +716,11 @@ impl Transaction for TxEip4844 { self.nonce } - fn gas_limit(&self) -> u64 { + fn gas_limit(&self) -> u128 { self.gas_limit } - fn gas_price(&self) -> Option { + fn gas_price(&self) -> Option { None } } @@ -931,11 +931,11 @@ impl Transaction for TxEip4844WithSidecar { self.tx.chain_id() } - fn gas_limit(&self) -> u64 { + fn gas_limit(&self) -> u128 { self.tx.gas_limit() } - fn gas_price(&self) -> Option { + fn gas_price(&self) -> Option { self.tx.gas_price() } diff --git a/crates/consensus/src/transaction/envelope.rs b/crates/consensus/src/transaction/envelope.rs index ebd057ddfda..859aabae486 100644 --- a/crates/consensus/src/transaction/envelope.rs +++ b/crates/consensus/src/transaction/envelope.rs @@ -484,7 +484,7 @@ mod tests { chain_id: u64::MAX, nonce: u64::MAX, gas_price: u128::MAX, - gas_limit: u64::MAX, + gas_limit: u128::MAX, to: TxKind::Call(Address::random()), value: U256::MAX, input: Bytes::new(), diff --git a/crates/consensus/src/transaction/legacy.rs b/crates/consensus/src/transaction/legacy.rs index 02f80bf97af..5a4897bcc88 100644 --- a/crates/consensus/src/transaction/legacy.rs +++ b/crates/consensus/src/transaction/legacy.rs @@ -35,8 +35,8 @@ pub struct TxLegacy { /// this transaction. This is paid up-front, before any /// computation is done and may not be increased /// later; formally Tg. - #[cfg_attr(feature = "serde", serde(with = "alloy_serde::u64_hex_or_decimal"))] - pub gas_limit: u64, + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::u128_hex_or_decimal"))] + pub gas_limit: u128, /// The 160-bit address of the message call’s recipient or, for a contract creation /// transaction, ∅, used here to denote the only member of B0 ; formally Tt. #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "TxKind::is_create"))] @@ -213,12 +213,12 @@ impl Transaction for TxLegacy { self.nonce } - fn gas_limit(&self) -> u64 { + fn gas_limit(&self) -> u128 { self.gas_limit } - fn gas_price(&self) -> Option { - Some(U256::from(self.gas_price)) + fn gas_price(&self) -> Option { + Some(self.gas_price) } } diff --git a/crates/consensus/src/transaction/mod.rs b/crates/consensus/src/transaction/mod.rs index a7fe001c360..caaab52ead5 100644 --- a/crates/consensus/src/transaction/mod.rs +++ b/crates/consensus/src/transaction/mod.rs @@ -42,10 +42,10 @@ pub trait Transaction: std::any::Any + Send + Sync + 'static { fn nonce(&self) -> u64; /// Get `gas_limit`. - fn gas_limit(&self) -> u64; + fn gas_limit(&self) -> u128; /// Get `gas_price`. - fn gas_price(&self) -> Option; + fn gas_price(&self) -> Option; } /// A signable transaction. diff --git a/crates/consensus/src/transaction/typed.rs b/crates/consensus/src/transaction/typed.rs index 401362b247e..2205b0542ec 100644 --- a/crates/consensus/src/transaction/typed.rs +++ b/crates/consensus/src/transaction/typed.rs @@ -96,7 +96,7 @@ impl Transaction for TypedTransaction { } } - fn gas_limit(&self) -> u64 { + fn gas_limit(&self) -> u128 { match self { Self::Legacy(tx) => tx.gas_limit(), Self::Eip2930(tx) => tx.gas_limit(), @@ -105,7 +105,7 @@ impl Transaction for TypedTransaction { } } - fn gas_price(&self) -> Option { + fn gas_price(&self) -> Option { match self { Self::Legacy(tx) => tx.gas_price(), Self::Eip2930(tx) => tx.gas_price(), diff --git a/crates/contract/src/call.rs b/crates/contract/src/call.rs index 9cc59186763..15f646f880a 100644 --- a/crates/contract/src/call.rs +++ b/crates/contract/src/call.rs @@ -306,7 +306,7 @@ impl, D: CallDecoder, N: Network> CallBu } /// Sets the `gas` field in the transaction to the provided value - pub fn gas(mut self, gas: U256) -> Self { + pub fn gas(mut self, gas: u128) -> Self { self.request.set_gas_limit(gas); self } @@ -314,7 +314,7 @@ impl, D: CallDecoder, N: Network> CallBu /// Sets the `gas_price` field in the transaction to the provided value /// If the internal transaction is an EIP-1559 one, then it sets both /// `max_fee_per_gas` and `max_priority_fee_per_gas` to the same value - pub fn gas_price(mut self, gas_price: U256) -> Self { + pub fn gas_price(mut self, gas_price: u128) -> Self { self.request.set_gas_price(gas_price); self } @@ -362,7 +362,7 @@ impl, D: CallDecoder, N: Network> CallBu } /// Returns the estimated gas cost for the underlying transaction to be executed - pub async fn estimate_gas(&self) -> Result { + pub async fn estimate_gas(&self) -> Result { self.provider.estimate_gas(&self.request, self.block).await.map_err(Into::into) } diff --git a/crates/network/src/any/builder.rs b/crates/network/src/any/builder.rs index 426933e5ddf..065d114fe00 100644 --- a/crates/network/src/any/builder.rs +++ b/crates/network/src/any/builder.rs @@ -1,7 +1,6 @@ use std::ops::{Deref, DerefMut}; use alloy_consensus::BlobTransactionSidecar; -use alloy_primitives::U256; use alloy_rpc_types::{TransactionRequest, WithOtherFields}; use crate::{ @@ -57,43 +56,43 @@ impl TransactionBuilder for WithOtherFields { self.deref_mut().set_value(value) } - fn gas_price(&self) -> Option { + fn gas_price(&self) -> Option { self.deref().gas_price() } - fn set_gas_price(&mut self, gas_price: U256) { + fn set_gas_price(&mut self, gas_price: u128) { self.deref_mut().set_gas_price(gas_price); } - fn max_fee_per_gas(&self) -> Option { + fn max_fee_per_gas(&self) -> Option { self.deref().max_fee_per_gas() } - fn set_max_fee_per_gas(&mut self, max_fee_per_gas: U256) { + fn set_max_fee_per_gas(&mut self, max_fee_per_gas: u128) { self.deref_mut().set_max_fee_per_gas(max_fee_per_gas); } - fn max_priority_fee_per_gas(&self) -> Option { + fn max_priority_fee_per_gas(&self) -> Option { self.deref().max_priority_fee_per_gas() } - fn set_max_priority_fee_per_gas(&mut self, max_priority_fee_per_gas: U256) { + fn set_max_priority_fee_per_gas(&mut self, max_priority_fee_per_gas: u128) { self.deref_mut().set_max_priority_fee_per_gas(max_priority_fee_per_gas); } - fn max_fee_per_blob_gas(&self) -> Option { + fn max_fee_per_blob_gas(&self) -> Option { self.deref().max_fee_per_blob_gas() } - fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: U256) { + fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: u128) { self.deref_mut().set_max_fee_per_blob_gas(max_fee_per_blob_gas) } - fn gas_limit(&self) -> Option { + fn gas_limit(&self) -> Option { self.deref().gas_limit() } - fn set_gas_limit(&mut self, gas_limit: U256) { + fn set_gas_limit(&mut self, gas_limit: u128) { self.deref_mut().set_gas_limit(gas_limit); } diff --git a/crates/network/src/ethereum/builder.rs b/crates/network/src/ethereum/builder.rs index 4b42e6b1c49..f33c96d82f0 100644 --- a/crates/network/src/ethereum/builder.rs +++ b/crates/network/src/ethereum/builder.rs @@ -4,7 +4,7 @@ use crate::{ use alloy_consensus::{ BlobTransactionSidecar, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant, TxLegacy, }; -use alloy_primitives::{Address, TxKind, U256}; +use alloy_primitives::{Address, TxKind}; use alloy_rpc_types::request::TransactionRequest; impl TransactionBuilder for alloy_rpc_types::TransactionRequest { @@ -59,43 +59,43 @@ impl TransactionBuilder for alloy_rpc_types::TransactionRequest { self.value = Some(value) } - fn gas_price(&self) -> Option { + fn gas_price(&self) -> Option { self.gas_price } - fn set_gas_price(&mut self, gas_price: U256) { + fn set_gas_price(&mut self, gas_price: u128) { self.gas_price = Some(gas_price); } - fn max_fee_per_gas(&self) -> Option { + fn max_fee_per_gas(&self) -> Option { self.max_fee_per_gas } - fn set_max_fee_per_gas(&mut self, max_fee_per_gas: U256) { + fn set_max_fee_per_gas(&mut self, max_fee_per_gas: u128) { self.max_fee_per_gas = Some(max_fee_per_gas); } - fn max_priority_fee_per_gas(&self) -> Option { + fn max_priority_fee_per_gas(&self) -> Option { self.max_priority_fee_per_gas } - fn set_max_priority_fee_per_gas(&mut self, max_priority_fee_per_gas: U256) { + fn set_max_priority_fee_per_gas(&mut self, max_priority_fee_per_gas: u128) { self.max_priority_fee_per_gas = Some(max_priority_fee_per_gas); } - fn max_fee_per_blob_gas(&self) -> Option { + fn max_fee_per_blob_gas(&self) -> Option { self.max_fee_per_blob_gas } - fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: U256) { + fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: u128) { self.max_fee_per_blob_gas = Some(max_fee_per_blob_gas) } - fn gas_limit(&self) -> Option { + fn gas_limit(&self) -> Option { self.gas } - fn set_gas_limit(&mut self, gas_limit: U256) { + fn set_gas_limit(&mut self, gas_limit: u128) { self.gas = Some(gas_limit); } @@ -158,12 +158,8 @@ fn build_legacy(request: TransactionRequest) -> Result Result Result Result Result: Default + Sized + Send + Sync + 'stati } /// Get the legacy gas price for the transaction. - fn gas_price(&self) -> Option; + fn gas_price(&self) -> Option; /// Set the legacy gas price for the transaction. - fn set_gas_price(&mut self, gas_price: U256); + fn set_gas_price(&mut self, gas_price: u128); /// Builder-pattern method for setting the legacy gas price. - fn with_gas_price(mut self, gas_price: U256) -> Self { + fn with_gas_price(mut self, gas_price: u128) -> Self { self.set_gas_price(gas_price); self } /// Get the max fee per gas for the transaction. - fn max_fee_per_gas(&self) -> Option; + fn max_fee_per_gas(&self) -> Option; /// Set the max fee per gas for the transaction. - fn set_max_fee_per_gas(&mut self, max_fee_per_gas: U256); + fn set_max_fee_per_gas(&mut self, max_fee_per_gas: u128); /// Builder-pattern method for setting max fee per gas . - fn with_max_fee_per_gas(mut self, max_fee_per_gas: U256) -> Self { + fn with_max_fee_per_gas(mut self, max_fee_per_gas: u128) -> Self { self.set_max_fee_per_gas(max_fee_per_gas); self } /// Get the max priority fee per gas for the transaction. - fn max_priority_fee_per_gas(&self) -> Option; + fn max_priority_fee_per_gas(&self) -> Option; /// Set the max priority fee per gas for the transaction. - fn set_max_priority_fee_per_gas(&mut self, max_priority_fee_per_gas: U256); + fn set_max_priority_fee_per_gas(&mut self, max_priority_fee_per_gas: u128); /// Builder-pattern method for setting max priority fee per gas. - fn with_max_priority_fee_per_gas(mut self, max_priority_fee_per_gas: U256) -> Self { + fn with_max_priority_fee_per_gas(mut self, max_priority_fee_per_gas: u128) -> Self { self.set_max_priority_fee_per_gas(max_priority_fee_per_gas); self } /// Get the max fee per blob gas for the transaction. - fn max_fee_per_blob_gas(&self) -> Option; + fn max_fee_per_blob_gas(&self) -> Option; /// Set the max fee per blob gas for the transaction. - fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: U256); + fn set_max_fee_per_blob_gas(&mut self, max_fee_per_blob_gas: u128); /// Builder-pattern method for setting max fee per blob gas . - fn with_max_fee_per_blob_gas(mut self, max_fee_per_blob_gas: U256) -> Self { + fn with_max_fee_per_blob_gas(mut self, max_fee_per_blob_gas: u128) -> Self { self.set_max_fee_per_blob_gas(max_fee_per_blob_gas); self } /// Get the gas limit for the transaction. - fn gas_limit(&self) -> Option; + fn gas_limit(&self) -> Option; /// Set the gas limit for the transaction. - fn set_gas_limit(&mut self, gas_limit: U256); + fn set_gas_limit(&mut self, gas_limit: u128); /// Builder-pattern method for setting the gas limit. - fn with_gas_limit(mut self, gas_limit: U256) -> Self { + fn with_gas_limit(mut self, gas_limit: u128) -> Self { self.set_gas_limit(gas_limit); self } diff --git a/crates/provider/src/layers/gas.rs b/crates/provider/src/layers/gas.rs index 555cb3e0a72..0b4d15949d3 100644 --- a/crates/provider/src/layers/gas.rs +++ b/crates/provider/src/layers/gas.rs @@ -3,7 +3,6 @@ use crate::{ }; use alloy_json_rpc::RpcError; use alloy_network::{Network, TransactionBuilder}; -use alloy_primitives::U256; use alloy_rpc_types::BlockNumberOrTag; use alloy_transport::{Transport, TransportError, TransportResult}; use async_trait::async_trait; @@ -81,12 +80,12 @@ where P: Provider, { /// Gets the gas_price to be used in legacy txs. - async fn get_gas_price(&self) -> TransportResult { + async fn get_gas_price(&self) -> TransportResult { self.inner.get_gas_price().await } /// Gets the gas_limit to be used in txs. - async fn get_gas_estimate(&self, tx: &N::TransactionRequest) -> TransportResult { + async fn get_gas_estimate(&self, tx: &N::TransactionRequest) -> TransportResult { self.inner.estimate_gas(tx, None).await } @@ -171,7 +170,7 @@ where .header .next_block_blob_fee() .ok_or(RpcError::UnsupportedFeature("eip4844"))?; - tx.set_max_fee_per_blob_gas(U256::from(next_blob_fee)); + tx.set_max_fee_per_blob_gas(next_blob_fee); } Ok(()) @@ -218,7 +217,7 @@ mod tests { use crate::ProviderBuilder; use alloy_network::EthereumSigner; use alloy_node_bindings::Anvil; - use alloy_primitives::address; + use alloy_primitives::{address, U256}; use alloy_rpc_client::RpcClient; use alloy_rpc_types::TransactionRequest; use alloy_transport_http::Http; diff --git a/crates/provider/src/layers/nonce.rs b/crates/provider/src/layers/nonce.rs index aae8636e75a..f00a68c3f52 100644 --- a/crates/provider/src/layers/nonce.rs +++ b/crates/provider/src/layers/nonce.rs @@ -96,8 +96,8 @@ where None => { // initialize the nonce if we haven't seen this account before let initial_nonce = self.inner.get_transaction_count(from, None).await?; - *nonce = Some(initial_nonce.to()); - Ok(initial_nonce.to()) + *nonce = Some(initial_nonce); + Ok(initial_nonce) } } } @@ -159,8 +159,8 @@ mod tests { let tx = TransactionRequest { value: Some(U256::from(100)), to: address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into(), - gas_price: Some(U256::from(20e9)), - gas: Some(U256::from(21000)), + gas_price: Some(20e9 as u128), + gas: Some(21000), ..Default::default() }; @@ -186,8 +186,8 @@ mod tests { from: Some(from), value: Some(U256::from(100)), to: address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into(), - gas_price: Some(U256::from(20e9)), - gas: Some(U256::from(21000)), + gas_price: Some(20e9 as u128), + gas: Some(21000), ..Default::default() }; diff --git a/crates/provider/src/layers/signer.rs b/crates/provider/src/layers/signer.rs index b66bef7e941..78d0013ca7f 100644 --- a/crates/provider/src/layers/signer.rs +++ b/crates/provider/src/layers/signer.rs @@ -124,8 +124,8 @@ mod tests { nonce: Some(0), value: Some(U256::from(100)), to: address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into(), - gas_price: Some(U256::from(20e9)), - gas: Some(U256::from(21000)), + gas_price: Some(20e9 as u128), + gas: Some(21000), ..Default::default() }; diff --git a/crates/provider/src/provider.rs b/crates/provider/src/provider.rs index c32906e4811..66d4714f767 100644 --- a/crates/provider/src/provider.rs +++ b/crates/provider/src/provider.rs @@ -9,7 +9,8 @@ use crate::{ use alloy_json_rpc::{RpcError, RpcParam, RpcReturn}; use alloy_network::{Ethereum, Network, TransactionBuilder}; use alloy_primitives::{ - hex, Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, TxHash, B256, U256, U64, + hex, Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, TxHash, B256, U128, + U256, U64, }; use alloy_rpc_client::{ BuiltInConnectionString, ClientBuilder, ClientRef, PollerBuilder, RpcClient, WeakClient, @@ -577,8 +578,11 @@ pub trait Provider: &self, address: Address, tag: Option, - ) -> TransportResult { - self.client().request("eth_getTransactionCount", (address, tag.unwrap_or_default())).await + ) -> TransportResult { + self.client() + .request("eth_getTransactionCount", (address, tag.unwrap_or_default())) + .await + .map(|count: U64| count.to::()) } /// Get a block by its number. @@ -689,13 +693,13 @@ pub trait Provider: } /// Gets the chain ID. - async fn get_chain_id(&self) -> TransportResult { - self.client().request("eth_chainId", ()).await + async fn get_chain_id(&self) -> TransportResult { + self.client().request("eth_chainId", ()).await.map(|id: U64| id.to::()) } /// Gets the network ID. Same as `eth_chainId`. - async fn get_net_version(&self) -> TransportResult { - self.client().request("net_version", ()).await + async fn get_net_version(&self) -> TransportResult { + self.client().request("net_version", ()).await.map(|id: U64| id.to::()) } /// Gets the specified storage value from [Address]. @@ -733,17 +737,20 @@ pub trait Provider: } /// Gets the current gas price in wei. - async fn get_gas_price(&self) -> TransportResult { - self.client().request("eth_gasPrice", ()).await + async fn get_gas_price(&self) -> TransportResult { + self.client().request("eth_gasPrice", ()).await.map(|price: U128| price.to::()) } /// Returns a suggestion for the current `maxPriorityFeePerGas` in wei. - async fn get_max_priority_fee_per_gas(&self) -> TransportResult { - self.client().request("eth_maxPriorityFeePerGas", ()).await + async fn get_max_priority_fee_per_gas(&self) -> TransportResult { + self.client() + .request("eth_maxPriorityFeePerGas", ()) + .await + .map(|fee: U128| fee.to::()) } /// Returns the base fee per blob gas (blob gas price) in wei. - async fn get_blob_base_fee(&self) -> TransportResult { + async fn get_blob_base_fee(&self) -> TransportResult { self.client().request("eth_blobBaseFee", ()).await } @@ -806,9 +813,10 @@ pub trait Provider: /// Returns a collection of historical gas information [FeeHistory] which /// can be used to calculate the EIP1559 fields `maxFeePerGas` and `maxPriorityFeePerGas`. + /// `block_count` can range from 1 to 1024 blocks in a single request. async fn get_fee_history( &self, - block_count: U256, + block_count: u64, last_block: BlockNumberOrTag, reward_percentiles: &[f64], ) -> TransportResult { @@ -820,11 +828,14 @@ pub trait Provider: &self, tx: &N::TransactionRequest, block: Option, - ) -> TransportResult { + ) -> TransportResult { if let Some(block_id) = block { - self.client().request("eth_estimateGas", (tx, block_id)).await + self.client() + .request("eth_estimateGas", (tx, block_id)) + .await + .map(|gas: U128| gas.to::()) } else { - self.client().request("eth_estimateGas", (tx,)).await + self.client().request("eth_estimateGas", (tx,)).await.map(|gas: U128| gas.to::()) } } @@ -838,7 +849,7 @@ pub trait Provider: ) -> TransportResult { let fee_history = self .get_fee_history( - U256::from(utils::EIP1559_FEE_ESTIMATION_PAST_BLOCKS), + utils::EIP1559_FEE_ESTIMATION_PAST_BLOCKS, BlockNumberOrTag::Latest, &[utils::EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE], ) @@ -847,7 +858,7 @@ pub trait Provider: // if the base fee of the Latest block is 0 then we need check if the latest block even has // a base fee/supports EIP1559 let base_fee_per_gas = match fee_history.latest_block_base_fee() { - Some(base_fee) if !base_fee.is_zero() => base_fee, + Some(base_fee) if (base_fee != 0) => base_fee, _ => { // empty response, fetch basefee from latest block directly self.get_block_by_number(BlockNumberOrTag::Latest, false) @@ -855,6 +866,7 @@ pub trait Provider: .ok_or(RpcError::NullResp)? .header .base_fee_per_gas + .map(|fee| fee.to::()) .ok_or(RpcError::UnsupportedFeature("eip1559"))? } }; @@ -1139,8 +1151,8 @@ mod tests { let tx = TransactionRequest { value: Some(U256::from(100)), to: address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into(), - gas_price: Some(U256::from(20e9)), - gas: Some(U256::from(21000)), + gas_price: Some(20e9 as u128), + gas: Some(21000), ..Default::default() }; @@ -1186,7 +1198,7 @@ mod tests { ) .await .unwrap(); - assert_eq!(count, U64::from(0)); + assert_eq!(count, 0); } #[tokio::test] @@ -1251,26 +1263,26 @@ mod tests { #[tokio::test] async fn gets_chain_id() { - let chain_id: u64 = 13371337; - let anvil = Anvil::new().args(["--chain-id", chain_id.to_string().as_str()]).spawn(); + let dev_chain_id: u64 = 13371337; + let anvil = Anvil::new().args(["--chain-id", dev_chain_id.to_string().as_str()]).spawn(); let url = anvil.endpoint().parse().unwrap(); let http = Http::::new(url); let provider = RootProvider::<_, Ethereum>::new(RpcClient::new(http, true)); let chain_id = provider.get_chain_id().await.unwrap(); - assert_eq!(chain_id, U64::from(chain_id)); + assert_eq!(chain_id, dev_chain_id); } #[tokio::test] async fn gets_network_id() { - let chain_id: u64 = 13371337; - let anvil = Anvil::new().args(["--chain-id", chain_id.to_string().as_str()]).spawn(); + let dev_chain_id: u64 = 13371337; + let anvil = Anvil::new().args(["--chain-id", dev_chain_id.to_string().as_str()]).spawn(); let url = anvil.endpoint().parse().unwrap(); let http = Http::::new(url); let provider = RootProvider::<_, Ethereum>::new(RpcClient::new(http, true)); let chain_id = provider.get_net_version().await.unwrap(); - assert_eq!(chain_id, U64::from(chain_id)); + assert_eq!(chain_id, dev_chain_id); } #[tokio::test] @@ -1314,7 +1326,7 @@ mod tests { tx.block_hash.unwrap(), b256!("b20e6f35d4b46b3c4cd72152faec7143da851a0dc281d390bdd50f58bfbdb5d3") ); - assert_eq!(tx.block_number.unwrap(), U256::from(4571819)); + assert_eq!(tx.block_number.unwrap(), 4571819); } #[tokio::test] @@ -1370,13 +1382,13 @@ mod tests { let block_number = provider.get_block_number().await.unwrap(); let fee_history = provider .get_fee_history( - U256::from(utils::EIP1559_FEE_ESTIMATION_PAST_BLOCKS), + utils::EIP1559_FEE_ESTIMATION_PAST_BLOCKS, BlockNumberOrTag::Number(block_number), &[utils::EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE], ) .await .unwrap(); - assert_eq!(fee_history.oldest_block, U256::ZERO); + assert_eq!(fee_history.oldest_block, 0_u64); } #[tokio::test] diff --git a/crates/provider/src/utils.rs b/crates/provider/src/utils.rs index d14e2ecb9fb..cec10f06595 100644 --- a/crates/provider/src/utils.rs +++ b/crates/provider/src/utils.rs @@ -1,31 +1,29 @@ //! Provider-related utilities. -use alloy_primitives::U256; - /// The number of blocks from the past for which the fee rewards are fetched for fee estimation. pub const EIP1559_FEE_ESTIMATION_PAST_BLOCKS: u64 = 10; /// Multiplier for the current base fee to estimate max base fee for the next block. -pub const EIP1559_BASE_FEE_MULTIPLIER: f64 = 2.0; +pub const EIP1559_BASE_FEE_MULTIPLIER: u128 = 2; /// The default percentile of gas premiums that are fetched for fee estimation. pub const EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE: f64 = 20.0; /// An estimator function for EIP1559 fees. -pub type EstimatorFunction = fn(U256, &[Vec]) -> Eip1559Estimation; +pub type EstimatorFunction = fn(u128, &[Vec]) -> Eip1559Estimation; /// Return type of EIP1155 gas fee estimator. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Eip1559Estimation { /// The base fee per gas. - pub max_fee_per_gas: U256, + pub max_fee_per_gas: u128, /// The max priority fee per gas. - pub max_priority_fee_per_gas: U256, + pub max_priority_fee_per_gas: u128, } -fn estimate_priority_fee(rewards: &[Vec]) -> U256 { +fn estimate_priority_fee(rewards: &[Vec]) -> u128 { let mut rewards = - rewards.iter().filter_map(|r| r.first()).filter(|r| **r > U256::ZERO).collect::>(); + rewards.iter().filter_map(|r| r.first()).filter(|r| **r > 0_u128).collect::>(); if rewards.is_empty() { - return U256::ZERO; + return 0_u128; } rewards.sort_unstable(); @@ -34,7 +32,7 @@ fn estimate_priority_fee(rewards: &[Vec]) -> U256 { let n = rewards.len(); if n % 2 == 0 { - (*rewards[n / 2 - 1] + *rewards[n / 2]) / U256::from(2) + (*rewards[n / 2 - 1] + *rewards[n / 2]) / 2 } else { *rewards[n / 2] } @@ -43,11 +41,11 @@ fn estimate_priority_fee(rewards: &[Vec]) -> U256 { /// The default EIP-1559 fee estimator which is based on the work by [MetaMask](https://github.com/MetaMask/core/blob/main/packages/gas-fee-controller/src/fetchGasEstimatesViaEthFeeHistory/calculateGasFeeEstimatesForPriorityLevels.ts#L56) /// (constants for "medium" priority level are used) pub fn eip1559_default_estimator( - base_fee_per_gas: U256, - rewards: &[Vec], + base_fee_per_gas: u128, + rewards: &[Vec], ) -> Eip1559Estimation { let max_priority_fee_per_gas = estimate_priority_fee(rewards); - let potential_max_fee = base_fee_per_gas * U256::from(EIP1559_BASE_FEE_MULTIPLIER); + let potential_max_fee = base_fee_per_gas * EIP1559_BASE_FEE_MULTIPLIER; Eip1559Estimation { max_fee_per_gas: potential_max_fee, max_priority_fee_per_gas } } @@ -59,42 +57,39 @@ mod tests { #[test] fn test_estimate_priority_fee() { - let rewards = vec![ - vec![U256::from(10_000_000_000_u64)], - vec![U256::from(200_000_000_000_u64)], - vec![U256::from(3_000_000_000_u64)], - ]; - assert_eq!(super::estimate_priority_fee(&rewards), U256::from(10_000_000_000_u64)); + let rewards = + vec![vec![10_000_000_000_u128], vec![200_000_000_000_u128], vec![3_000_000_000_u128]]; + assert_eq!(super::estimate_priority_fee(&rewards), 10_000_000_000_u128); let rewards = vec![ - vec![U256::from(400_000_000_000_u64)], - vec![U256::from(2_000_000_000_u64)], - vec![U256::from(5_000_000_000_u64)], - vec![U256::from(3_000_000_000_u64)], + vec![400_000_000_000_u128], + vec![2_000_000_000_u128], + vec![5_000_000_000_u128], + vec![3_000_000_000_u128], ]; - assert_eq!(super::estimate_priority_fee(&rewards), U256::from(4_000_000_000_u64)); + assert_eq!(super::estimate_priority_fee(&rewards), 4_000_000_000_u128); - let rewards = vec![vec![U256::from(0)], vec![U256::from(0)], vec![U256::from(0)]]; + let rewards = vec![vec![0_u128], vec![0_u128], vec![0_u128]]; - assert_eq!(super::estimate_priority_fee(&rewards), U256::from(0)); + assert_eq!(super::estimate_priority_fee(&rewards), 0_u128); - assert_eq!(super::estimate_priority_fee(&[]), U256::from(0)); + assert_eq!(super::estimate_priority_fee(&[]), 0_u128); } #[test] fn test_eip1559_default_estimator() { - let base_fee_per_gas = U256::from(1_000_000_000_u64); + let base_fee_per_gas = 1_000_000_000_u128; let rewards = vec![ - vec![U256::from(200_000_000_000_u64)], - vec![U256::from(200_000_000_000_u64)], - vec![U256::from(300_000_000_000_u64)], + vec![200_000_000_000_u128], + vec![200_000_000_000_u128], + vec![300_000_000_000_u128], ]; assert_eq!( super::eip1559_default_estimator(base_fee_per_gas, &rewards), Eip1559Estimation { - max_fee_per_gas: U256::from(2_000_000_000_u64), - max_priority_fee_per_gas: U256::from(200_000_000_000_u64) + max_fee_per_gas: 2_000_000_000_u128, + max_priority_fee_per_gas: 200_000_000_000_u128 } ); } diff --git a/crates/rpc-types/src/eth/fee.rs b/crates/rpc-types/src/eth/fee.rs index 49b88f97af0..61c3b1ab8ba 100644 --- a/crates/rpc-types/src/eth/fee.rs +++ b/crates/rpc-types/src/eth/fee.rs @@ -1,4 +1,3 @@ -use alloy_primitives::U256; use serde::{Deserialize, Serialize}; /// Internal struct to calculate reward percentiles @@ -37,60 +36,74 @@ pub struct FeeHistory { /// # Note /// /// Empty list is skipped only for compatibility with Erigon and Geth. - #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub base_fee_per_gas: Vec, + #[serde( + default, + skip_serializing_if = "Vec::is_empty", + with = "alloy_serde::num::u128_hex_or_decimal_vec" + )] + pub base_fee_per_gas: Vec, /// An array of block gas used ratios. These are calculated as the ratio /// of `gasUsed` and `gasLimit`. /// /// # Note /// /// The `Option` is only for compatibility with Erigon and Geth. + // #[serde(default, with = "alloy_serde::num::f64_hex_vec")] pub gas_used_ratio: Vec, /// An array of block base fees per blob gas. This includes the next block after the newest /// of the returned range, because this value can be derived from the newest block. Zeroes /// are returned for pre-EIP-4844 blocks. - #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub base_fee_per_blob_gas: Vec, + #[serde( + default, + skip_serializing_if = "Vec::is_empty", + // with = "alloy_serde::num::u128_hex_or_decimal_vec" + )] + pub base_fee_per_blob_gas: Vec, /// An array of block blob gas used ratios. These are calculated as the ratio of gasUsed and /// gasLimit. #[serde(default, skip_serializing_if = "Vec::is_empty")] pub blob_gas_used_ratio: Vec, /// Lowest number block of the returned range. - pub oldest_block: U256, + #[serde(default, with = "alloy_serde::num::u64_hex")] + pub oldest_block: u64, /// An (optional) array of effective priority fee per gas data points from a single /// block. All zeroes are returned if the block is empty. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub reward: Option>>, + #[serde( + default, + skip_serializing_if = "Option::is_none", + with = "alloy_serde::num::u128_hex_or_decimal_vec_vec_opt" + )] + pub reward: Option>>, } impl FeeHistory { /// Returns the base fee of the latest block in the `eth_feeHistory` request. - pub fn latest_block_base_fee(&self) -> Option { + pub fn latest_block_base_fee(&self) -> Option { // the base fee of requested block is the second last element in the // list self.base_fee_per_gas.iter().rev().nth(1).copied() } /// Returns the base fee of the next block. - pub fn next_block_base_fee(&self) -> Option { + pub fn next_block_base_fee(&self) -> Option { self.base_fee_per_gas.last().copied() } /// Returns the blob base fee of the next block. /// /// If the next block is pre- EIP-4844, this will return `None`. - pub fn next_block_blob_base_fee(&self) -> Option { + pub fn next_block_blob_base_fee(&self) -> Option { self.base_fee_per_blob_gas .last() .filter(|fee| { // skip zero value that is returned for pre-EIP-4844 blocks - !fee.is_zero() + **fee != 0 }) .copied() } /// Returns the blob fee of the latest block in the `eth_feeHistory` request. - pub fn latest_block_blob_base_fee(&self) -> Option { + pub fn latest_block_blob_base_fee(&self) -> Option { // the blob fee requested block is the second last element in the list self.base_fee_per_blob_gas .iter() @@ -98,7 +111,7 @@ impl FeeHistory { .nth(1) .filter(|fee| { // skip zero value that is returned for pre-EIP-4844 blocks - !fee.is_zero() + **fee != 0 }) .copied() } diff --git a/crates/rpc-types/src/eth/transaction/mod.rs b/crates/rpc-types/src/eth/transaction/mod.rs index bd040a45780..c9a3a1d9f75 100644 --- a/crates/rpc-types/src/eth/transaction/mod.rs +++ b/crates/rpc-types/src/eth/transaction/mod.rs @@ -5,7 +5,7 @@ use alloy_consensus::{ SignableTransaction, Signed, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant, TxEnvelope, TxLegacy, TxType, }; -use alloy_primitives::{Address, Bytes, B256, U256, U8}; +use alloy_primitives::{Address, Bytes, B256, U256}; use serde::{Deserialize, Serialize}; pub use alloy_consensus::BlobTransactionSidecar; @@ -43,9 +43,11 @@ pub struct Transaction { /// Block hash pub block_hash: Option, /// Block number - pub block_number: Option, + #[serde(with = "alloy_serde::num::u64_hex_opt")] + pub block_number: Option, /// Transaction Index - pub transaction_index: Option, + #[serde(with = "alloy_serde::num::u64_hex_opt")] + pub transaction_index: Option, /// Sender pub from: Address, /// Recipient @@ -53,19 +55,36 @@ pub struct Transaction { /// Transferred value pub value: U256, /// Gas Price - #[serde(skip_serializing_if = "Option::is_none")] - pub gas_price: Option, + #[serde( + default, + skip_serializing_if = "Option::is_none", + with = "alloy_serde::num::u128_hex_or_decimal_opt" + )] + pub gas_price: Option, /// Gas amount - pub gas: U256, + #[serde(with = "alloy_serde::num::u128_hex_or_decimal")] + pub gas: u128, /// Max BaseFeePerGas the user is willing to pay. - #[serde(skip_serializing_if = "Option::is_none")] - pub max_fee_per_gas: Option, + #[serde( + default, + skip_serializing_if = "Option::is_none", + with = "alloy_serde::num::u128_hex_or_decimal_opt" + )] + pub max_fee_per_gas: Option, /// The miner's tip. - #[serde(skip_serializing_if = "Option::is_none")] - pub max_priority_fee_per_gas: Option, + #[serde( + default, + skip_serializing_if = "Option::is_none", + with = "alloy_serde::num::u128_hex_or_decimal_opt" + )] + pub max_priority_fee_per_gas: Option, /// Configured max fee per blob gas for eip-4844 transactions - #[serde(skip_serializing_if = "Option::is_none")] - pub max_fee_per_blob_gas: Option, + #[serde( + default, + skip_serializing_if = "Option::is_none", + with = "alloy_serde::num::u128_hex_or_decimal_opt" + )] + pub max_fee_per_blob_gas: Option, /// Data pub input: Bytes, /// All _flattened_ fields of the transaction signature. @@ -88,8 +107,13 @@ pub struct Transaction { /// /// Transaction type, Some(2) for EIP-1559 transaction, /// Some(1) for AccessList transaction, None for Legacy - #[serde(rename = "type", skip_serializing_if = "Option::is_none")] - pub transaction_type: Option, + #[serde( + default, + rename = "type", + skip_serializing_if = "Option::is_none", + with = "alloy_serde::num::u8_hex_opt" + )] + pub transaction_type: Option, /// Arbitrary extra fields. /// @@ -142,8 +166,8 @@ impl TryFrom for Signed { let tx = TxLegacy { chain_id: tx.chain_id, nonce: tx.nonce, - gas_price: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?.to(), - gas_limit: tx.gas.to(), + gas_price: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?, + gas_limit: tx.gas, to: tx.to.into(), value: tx.value, input: tx.input, @@ -161,12 +185,11 @@ impl TryFrom for Signed { let tx = TxEip1559 { chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?, nonce: tx.nonce, - max_fee_per_gas: tx.max_fee_per_gas.ok_or(ConversionError::MissingMaxFeePerGas)?.to(), + max_fee_per_gas: tx.max_fee_per_gas.ok_or(ConversionError::MissingMaxFeePerGas)?, max_priority_fee_per_gas: tx .max_priority_fee_per_gas - .ok_or(ConversionError::MissingMaxPriorityFeePerGas)? - .to(), - gas_limit: tx.gas.to(), + .ok_or(ConversionError::MissingMaxPriorityFeePerGas)?, + gas_limit: tx.gas, to: tx.to.into(), value: tx.value, input: tx.input, @@ -185,8 +208,8 @@ impl TryFrom for Signed { let tx = TxEip2930 { chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?, nonce: tx.nonce, - gas_price: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?.to(), - gas_limit: tx.gas.to(), + gas_price: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?, + gas_limit: tx.gas, to: tx.to.into(), value: tx.value, input: tx.input, @@ -204,12 +227,11 @@ impl TryFrom for Signed { let tx = TxEip4844 { chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?, nonce: tx.nonce, - max_fee_per_gas: tx.max_fee_per_gas.ok_or(ConversionError::MissingMaxFeePerGas)?.to(), + max_fee_per_gas: tx.max_fee_per_gas.ok_or(ConversionError::MissingMaxFeePerGas)?, max_priority_fee_per_gas: tx .max_priority_fee_per_gas - .ok_or(ConversionError::MissingMaxPriorityFeePerGas)? - .to(), - gas_limit: tx.gas.to(), + .ok_or(ConversionError::MissingMaxPriorityFeePerGas)?, + gas_limit: tx.gas, to: tx.to.ok_or(ConversionError::MissingTo)?, value: tx.value, input: tx.input, @@ -217,8 +239,7 @@ impl TryFrom for Signed { blob_versioned_hashes: tx.blob_versioned_hashes.unwrap_or_default(), max_fee_per_blob_gas: tx .max_fee_per_blob_gas - .ok_or(ConversionError::MissingMaxFeePerBlobGas)? - .to(), + .ok_or(ConversionError::MissingMaxFeePerBlobGas)?, }; Ok(tx.into_signed(signature)) } @@ -240,7 +261,7 @@ impl TryFrom for TxEnvelope { type Error = ConversionError; fn try_from(tx: Transaction) -> Result { - match tx.transaction_type.unwrap_or_default().to::().try_into()? { + match tx.transaction_type.unwrap_or_default().try_into()? { TxType::Legacy => Ok(Self::Legacy(tx.try_into()?)), TxType::Eip1559 => Ok(Self::Eip1559(tx.try_into()?)), TxType::Eip2930 => Ok(Self::Eip2930(tx.try_into()?)), @@ -269,13 +290,13 @@ mod tests { hash: B256::with_last_byte(1), nonce: 2, block_hash: Some(B256::with_last_byte(3)), - block_number: Some(U256::from(4)), - transaction_index: Some(U256::from(5)), + block_number: Some(4), + transaction_index: Some(5), from: Address::with_last_byte(6), to: Some(Address::with_last_byte(7)), value: U256::from(8), - gas_price: Some(U256::from(9)), - gas: U256::from(10), + gas_price: Some(9), + gas: 10, input: Bytes::from(vec![11, 12, 13]), signature: Some(Signature { v: U256::from(14), @@ -286,9 +307,9 @@ mod tests { chain_id: Some(17), blob_versioned_hashes: None, access_list: None, - transaction_type: Some(U8::from(20)), - max_fee_per_gas: Some(U256::from(21)), - max_priority_fee_per_gas: Some(U256::from(22)), + transaction_type: Some(20), + max_fee_per_gas: Some(21), + max_priority_fee_per_gas: Some(22), max_fee_per_blob_gas: None, other: Default::default(), }; @@ -307,13 +328,13 @@ mod tests { hash: B256::with_last_byte(1), nonce: 2, block_hash: Some(B256::with_last_byte(3)), - block_number: Some(U256::from(4)), - transaction_index: Some(U256::from(5)), + block_number: Some(4), + transaction_index: Some(5), from: Address::with_last_byte(6), to: Some(Address::with_last_byte(7)), value: U256::from(8), - gas_price: Some(U256::from(9)), - gas: U256::from(10), + gas_price: Some(9), + gas: 10, input: Bytes::from(vec![11, 12, 13]), signature: Some(Signature { v: U256::from(14), @@ -324,9 +345,9 @@ mod tests { chain_id: Some(17), blob_versioned_hashes: None, access_list: None, - transaction_type: Some(U8::from(20)), - max_fee_per_gas: Some(U256::from(21)), - max_priority_fee_per_gas: Some(U256::from(22)), + transaction_type: Some(20), + max_fee_per_gas: Some(21), + max_priority_fee_per_gas: Some(22), max_fee_per_blob_gas: None, other: Default::default(), }; @@ -346,7 +367,7 @@ mod tests { nonce: 2, from: Address::with_last_byte(6), value: U256::from(8), - gas: U256::from(10), + gas: 10, input: Bytes::from(vec![11, 12, 13]), ..Default::default() }; diff --git a/crates/rpc-types/src/eth/transaction/receipt.rs b/crates/rpc-types/src/eth/transaction/receipt.rs index 19b700d8323..1880f8deb21 100644 --- a/crates/rpc-types/src/eth/transaction/receipt.rs +++ b/crates/rpc-types/src/eth/transaction/receipt.rs @@ -116,7 +116,6 @@ impl TransactionReceipt { #[cfg(test)] mod test { - use super::*; use alloy_consensus::{Receipt, ReceiptWithBloom}; use alloy_primitives::{address, b256, bloom, Bloom}; diff --git a/crates/rpc-types/src/eth/transaction/request.rs b/crates/rpc-types/src/eth/transaction/request.rs index 0ef12a61c7c..8d3a568407f 100644 --- a/crates/rpc-types/src/eth/transaction/request.rs +++ b/crates/rpc-types/src/eth/transaction/request.rs @@ -1,7 +1,7 @@ //! Alloy basic Transaction Request type. use crate::{eth::transaction::AccessList, BlobTransactionSidecar, Transaction}; -use alloy_primitives::{Address, Bytes, ChainId, B256, U256, U8}; +use alloy_primitives::{Address, Bytes, ChainId, B256, U256}; use serde::{Deserialize, Serialize}; use std::hash::Hash; @@ -15,18 +15,18 @@ pub struct TransactionRequest { pub to: Option
, /// The legacy gas price. #[serde(default)] - pub gas_price: Option, + pub gas_price: Option, /// The max base fee per gas the sender is willing to pay. #[serde(default)] - pub max_fee_per_gas: Option, + pub max_fee_per_gas: Option, /// The max priority fee per gas the sender is willing to pay, also called the miner tip. #[serde(default)] - pub max_priority_fee_per_gas: Option, + pub max_priority_fee_per_gas: Option, /// The max fee per blob gas for EIP-4844 blob transactions. #[serde(skip_serializing_if = "Option::is_none")] - pub max_fee_per_blob_gas: Option, + pub max_fee_per_blob_gas: Option, /// The gas limit for the transaction. - pub gas: Option, + pub gas: Option, /// The value transferred in the transaction, in wei. pub value: Option, /// Transaction data. @@ -42,8 +42,8 @@ pub struct TransactionRequest { #[serde(default)] pub access_list: Option, /// The EIP-2718 transaction type. See [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) for more information. - #[serde(rename = "type")] - pub transaction_type: Option, + #[serde(default, rename = "type", with = "alloy_serde::num::u8_hex_opt")] + pub transaction_type: Option, /// Blob versioned hashes for EIP-4844 transactions. #[serde(skip_serializing_if = "Option::is_none")] pub blob_versioned_hashes: Option>, @@ -79,7 +79,7 @@ impl TransactionRequest { /// /// The returns `gas_price` (legacy) if set or `max_fee_per_gas` (EIP1559) #[inline] - pub fn fee_cap(&self) -> Option { + pub fn fee_cap(&self) -> Option { self.gas_price.or(self.max_fee_per_gas) } @@ -97,7 +97,7 @@ impl TransactionRequest { } /// Sets the gas limit for the transaction. - pub const fn gas_limit(mut self, gas_limit: U256) -> Self { + pub const fn gas_limit(mut self, gas_limit: u128) -> Self { self.gas = Some(gas_limit); self } @@ -109,13 +109,13 @@ impl TransactionRequest { } /// Sets the maximum fee per gas for the transaction. - pub const fn max_fee_per_gas(mut self, max_fee_per_gas: U256) -> Self { + pub const fn max_fee_per_gas(mut self, max_fee_per_gas: u128) -> Self { self.max_fee_per_gas = Some(max_fee_per_gas); self } /// Sets the maximum priority fee per gas for the transaction. - pub const fn max_priority_fee_per_gas(mut self, max_priority_fee_per_gas: U256) -> Self { + pub const fn max_priority_fee_per_gas(mut self, max_priority_fee_per_gas: u128) -> Self { self.max_priority_fee_per_gas = Some(max_priority_fee_per_gas); self } @@ -146,8 +146,8 @@ impl TransactionRequest { } /// Sets the transactions type for the transactions. - pub fn transaction_type(mut self, transaction_type: u8) -> Self { - self.transaction_type = Some(U8::from(transaction_type)); + pub const fn transaction_type(mut self, transaction_type: u8) -> Self { + self.transaction_type = Some(transaction_type); self } } diff --git a/crates/rpc-types/src/eth/transaction/tx_type.rs b/crates/rpc-types/src/eth/transaction/tx_type.rs index f589f639cb0..f4ad3b0ade6 100644 --- a/crates/rpc-types/src/eth/transaction/tx_type.rs +++ b/crates/rpc-types/src/eth/transaction/tx_type.rs @@ -44,9 +44,3 @@ impl From for u8 { } } } - -impl From for U8 { - fn from(value: TxType) -> Self { - U8::from(u8::from(value)) - } -} diff --git a/crates/serde/src/num.rs b/crates/serde/src/num.rs index 33167cdbc30..c1eaf2a6bef 100644 --- a/crates/serde/src/num.rs +++ b/crates/serde/src/num.rs @@ -264,9 +264,96 @@ pub mod u128_hex_or_decimal { } } +/// serde functions for handling primitive optional `u128` as [U128](alloy_primitives::U128) +pub mod u128_hex_or_decimal_opt { + use alloy_primitives::U128; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + + /// Deserializes an `Option` accepting a hex quantity string with optional 0x prefix or + /// a number + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + match Option::::deserialize(deserializer)? { + Some(val) => Ok(Some(val.to())), + None => Ok(None), + } + } + + /// Serializes `Option` as hex string + pub fn serialize(value: &Option, s: S) -> Result { + match value { + Some(val) => U128::from(*val).serialize(s), + None => s.serialize_none(), + } + } +} + +/// serde functions for handling `Vec` as [U128](alloy_primitives::U128) +pub mod u128_hex_or_decimal_vec { + use alloc::vec::Vec; + use alloy_primitives::U128; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + /// Deserializes an `u128` accepting a hex quantity string with optional 0x prefix or + /// a number + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + let vec = Vec::::deserialize(deserializer)?; + Ok(vec.into_iter().map(|val| val.to()).collect()) + } + + /// Serializes u128 as hex string + pub fn serialize(value: &[u128], s: S) -> Result { + let vec = value.iter().map(|val| U128::from(*val)).collect::>(); + vec.serialize(s) + } +} + +/// serde functions for handling `Vec>` as [U128](alloy_primitives::U128) +pub mod u128_hex_or_decimal_vec_vec_opt { + use alloc::vec::Vec; + use alloy_primitives::U128; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + + /// Deserializes an `u128` accepting a hex quantity string with optional 0x prefix or + /// a number + pub fn deserialize<'de, D>(deserializer: D) -> Result>>, D::Error> + where + D: Deserializer<'de>, + { + match Option::>>::deserialize(deserializer)? { + Some(vec) => Ok(Some( + vec.into_iter().map(|v| v.into_iter().map(|val| val.to()).collect()).collect(), + )), + None => Ok(None), + } + } + + /// Serializes u128 as hex string + pub fn serialize( + value: &Option>>, + s: S, + ) -> Result { + match value { + Some(vec) => { + let vec = vec + .iter() + .map(|v| v.iter().map(|val| U128::from(*val)).collect::>()) + .collect::>(); + vec.serialize(s) + } + None => s.serialize_none(), + } + } +} + #[cfg(test)] mod tests { use super::*; + use alloc::{vec, vec::Vec}; use serde::{Deserialize, Serialize}; #[test] @@ -305,4 +392,71 @@ mod tests { assert_eq!(val, deserialized); } + + #[test] + fn test_u128_hex_or_decimal_opt() { + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct Value { + #[serde(with = "u128_hex_or_decimal_opt")] + inner: Option, + } + + let val = Value { inner: Some(1000) }; + let s = serde_json::to_string(&val).unwrap(); + assert_eq!(s, "{\"inner\":\"0x3e8\"}"); + + let deserialized: Value = serde_json::from_str(&s).unwrap(); + assert_eq!(val, deserialized); + + let s = "{\"inner\":\"1000\"}".to_string(); + let deserialized: Value = serde_json::from_str(&s).unwrap(); + + assert_eq!(val, deserialized); + + let val = Value { inner: None }; + let s = serde_json::to_string(&val).unwrap(); + assert_eq!(s, "{\"inner\":null}"); + + let deserialized: Value = serde_json::from_str(&s).unwrap(); + assert_eq!(val, deserialized); + } + + #[test] + fn test_u128_hex_or_decimal_vec() { + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct Value { + #[serde(with = "u128_hex_or_decimal_vec")] + inner: Vec, + } + + let val = Value { inner: vec![1000, 2000] }; + let s = serde_json::to_string(&val).unwrap(); + assert_eq!(s, "{\"inner\":[\"0x3e8\",\"0x7d0\"]}"); + + let deserialized: Value = serde_json::from_str(&s).unwrap(); + assert_eq!(val, deserialized); + } + + #[test] + fn test_u128_hex_or_decimal_vec_vec_opt() { + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct Value { + #[serde(with = "u128_hex_or_decimal_vec_vec_opt")] + inner: Option>>, + } + + let val = Value { inner: Some(vec![vec![1000, 2000], vec![3000, 4000]]) }; + let s = serde_json::to_string(&val).unwrap(); + assert_eq!(s, "{\"inner\":[[\"0x3e8\",\"0x7d0\"],[\"0xbb8\",\"0xfa0\"]]}"); + + let deserialized: Value = serde_json::from_str(&s).unwrap(); + assert_eq!(val, deserialized); + + let val = Value { inner: None }; + let s = serde_json::to_string(&val).unwrap(); + assert_eq!(s, "{\"inner\":null}"); + + let deserialized: Value = serde_json::from_str(&s).unwrap(); + assert_eq!(val, deserialized); + } } diff --git a/crates/signer-trezor/src/signer.rs b/crates/signer-trezor/src/signer.rs index d7d7231d92f..16f03c70021 100644 --- a/crates/signer-trezor/src/signer.rs +++ b/crates/signer-trezor/src/signer.rs @@ -164,11 +164,11 @@ impl TrezorSigner { let nonce = tx.nonce(); let nonce = u64_to_trezor(nonce); - let gas_price = U256::ZERO; - let gas_price = u256_to_trezor(gas_price); + let gas_price = 0_u128; + let gas_price = u128_to_trezor(gas_price); let gas_limit = tx.gas_limit(); - let gas_limit = u64_to_trezor(gas_limit); + let gas_limit = u128_to_trezor(gas_limit); let to = match tx.to() { TxKind::Call(to) => address_to_trezor(&to),