diff --git a/src/api/eth.rs b/src/api/eth.rs index 3bb1d423..74bd63e3 100644 --- a/src/api/eth.rs +++ b/src/api/eth.rs @@ -486,6 +486,7 @@ mod tests { from: None, to: Some(Address::from_low_u64_be(0x123)), gas: None, gas_price: None, value: Some(0x1.into()), data: None, + transaction_type: None, access_list: None, }, None => "eth_call", vec![r#"{"to":"0x0000000000000000000000000000000000000123","value":"0x1"}"#, r#""latest""#]; @@ -517,6 +518,7 @@ mod tests { from: None, to: Some(Address::from_low_u64_be(0x123)), gas: None, gas_price: None, value: Some(0x1.into()), data: None, + transaction_type: None, access_list: None, }, None => "eth_estimateGas", vec![r#"{"to":"0x0000000000000000000000000000000000000123","value":"0x1"}"#]; @@ -528,6 +530,7 @@ mod tests { from: None, to: None, gas: None, gas_price: None, value: Some(0x1.into()), data: None, + transaction_type: None, access_list: None, }, None => "eth_estimateGas", vec![r#"{"value":"0x1"}"#]; @@ -539,6 +542,7 @@ mod tests { from: None, to: Some(Address::from_low_u64_be(0x123)), gas: None, gas_price: None, value: Some(0x1.into()), data: None, + transaction_type: None, access_list: None, }, Some(0x123.into()) => "eth_estimateGas", vec![r#"{"to":"0x0000000000000000000000000000000000000123","value":"0x1"}"#, r#""0x123""#]; @@ -776,6 +780,7 @@ mod tests { gas: None, gas_price: Some(0x1.into()), value: Some(0x1.into()), data: None, nonce: None, condition: None, + transaction_type: None, access_list: None, } => "eth_sendTransaction", vec![r#"{"from":"0x0000000000000000000000000000000000000123","gasPrice":"0x1","to":"0x0000000000000000000000000000000000000123","value":"0x1"}"#]; diff --git a/src/api/parity.rs b/src/api/parity.rs index 789d988c..215a5342 100644 --- a/src/api/parity.rs +++ b/src/api/parity.rs @@ -97,6 +97,8 @@ mod tests { gas_price: None, value: Some(0x1.into()), data: None, + transaction_type: None, + access_list: None, }, CallRequest { from: Some(Address::from_low_u64_be(0x321)), @@ -105,6 +107,8 @@ mod tests { gas_price: None, value: None, data: Some(hex!("0493").into()), + transaction_type: None, + access_list: None, }, CallRequest { from: None, @@ -112,7 +116,9 @@ mod tests { gas: None, gas_price: None, value: Some(0x5.into()), - data: Some(hex!("0723").into()) + data: Some(hex!("0723").into()), + transaction_type: None, + access_list: None, } ] => "parity_call", vec![ r#"[{"to":"0x0000000000000000000000000000000000000123","value":"0x1"},{"data":"0x0493","from":"0x0000000000000000000000000000000000000321","to":"0x0000000000000000000000000000000000000123"},{"data":"0x0723","to":"0x0000000000000000000000000000000000000765","value":"0x5"}]"# diff --git a/src/api/personal.rs b/src/api/personal.rs index b21610b4..15c36c2e 100644 --- a/src/api/personal.rs +++ b/src/api/personal.rs @@ -142,6 +142,7 @@ mod tests { gas: None, gas_price: Some(0x1.into()), value: Some(0x1.into()), data: None, nonce: None, condition: None, + transaction_type: None, access_list: None, }, "hunter2" => "personal_sendTransaction", vec![r#"{"from":"0x0000000000000000000000000000000000000123","gasPrice":"0x1","to":"0x0000000000000000000000000000000000000123","value":"0x1"}"#, r#""hunter2""#]; @@ -158,6 +159,8 @@ mod tests { data: Some(hex!("603880600c6000396000f300603880600c6000396000f3603880600c6000396000f360").into()), nonce: Some(0x0.into()), condition: None, + transaction_type: None, + access_list: None, }, "hunter2" => "personal_signTransaction", vec![r#"{"data":"0x603880600c6000396000f300603880600c6000396000f3603880600c6000396000f360","from":"0x407d73d8a49eeb85d32cf465507dd71d507100c1","gas":"0x7f110","gasPrice":"0x9184e72a000","nonce":"0x0","to":"0x853f43d8a49eeb85d32cf465507dd71d507100c1","value":"0x7f110"}"#, r#""hunter2""#]; diff --git a/src/api/traces.rs b/src/api/traces.rs index c6f9f410..dee5d729 100644 --- a/src/api/traces.rs +++ b/src/api/traces.rs @@ -216,6 +216,7 @@ mod tests { from: None, to: Some(Address::from_low_u64_be(0x123)), gas: None, gas_price: None, value: Some(0x1.into()), data: None, + transaction_type: None, access_list: None, }, vec![TraceType::Trace], None => "trace_call", vec![r#"{"to":"0x0000000000000000000000000000000000000123","value":"0x1"}"#, r#"["trace"]"#, r#""latest""#]; diff --git a/src/confirm.rs b/src/confirm.rs index 7bde074a..1272bc7d 100644 --- a/src/confirm.rs +++ b/src/confirm.rs @@ -141,6 +141,8 @@ mod tests { data: None, nonce: None, condition: None, + transaction_type: None, + access_list: None, }; let transaction_receipt = TransactionReceipt { @@ -155,6 +157,7 @@ mod tests { status: Some(1.into()), root: Some(H256::zero()), logs_bloom: Default::default(), + transaction_type: None, }; let poll_interval = Duration::from_secs(0); diff --git a/src/contract/deploy.rs b/src/contract/deploy.rs index 0e819187..85345b60 100644 --- a/src/contract/deploy.rs +++ b/src/contract/deploy.rs @@ -137,6 +137,8 @@ impl Builder { .data .expect("Tried to deploy a contract but transaction data wasn't set"), chain_id, + transaction_type: tx.transaction_type, + access_list: tx.access_list, }; let signed_tx = crate::api::Accounts::new(transport.clone()) .sign_transaction(tx, from) @@ -204,6 +206,8 @@ impl Builder { nonce: options.nonce, data: Some(Bytes(data)), condition: options.condition, + transaction_type: options.transaction_type, + access_list: options.access_list, }; let receipt = send(tx).await?; match receipt.status { diff --git a/src/contract/mod.rs b/src/contract/mod.rs index ec471c2d..84876555 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -6,8 +6,8 @@ use crate::{ contract::tokens::{Detokenize, Tokenize}, futures::Future, types::{ - Address, BlockId, Bytes, CallRequest, FilterBuilder, TransactionCondition, TransactionReceipt, - TransactionRequest, H256, U256, + AccessList, Address, BlockId, Bytes, CallRequest, FilterBuilder, TransactionCondition, TransactionReceipt, + TransactionRequest, H256, U256, U64, }, Transport, }; @@ -35,6 +35,10 @@ pub struct Options { pub nonce: Option, /// A condition to satisfy before including transaction. pub condition: Option, + /// Transaction type, Some(1) for AccessList transaction, None for Legacy + pub transaction_type: Option, + /// Access list + pub access_list: Option, } impl Options { @@ -127,6 +131,8 @@ impl Contract { value, nonce, condition, + transaction_type, + access_list, } = options; self.eth .send_transaction(TransactionRequest { @@ -138,6 +144,8 @@ impl Contract { nonce, data: Some(Bytes(data)), condition, + transaction_type, + access_list, }) .await .map_err(Error::from) @@ -170,6 +178,8 @@ impl Contract { nonce: options.nonce, data: Some(Bytes(fn_data)), condition: options.condition, + transaction_type: options.transaction_type, + access_list: options.access_list, }; confirm::send_transaction_with_confirmation( self.eth.transport().clone(), @@ -195,6 +205,8 @@ impl Contract { gas_price: options.gas_price, value: options.value, data: Some(Bytes(data)), + transaction_type: options.transaction_type, + access_list: options.access_list, }, None, ) @@ -234,6 +246,8 @@ impl Contract { gas_price: options.gas_price, value: options.value, data: Some(Bytes(call)), + transaction_type: options.transaction_type, + access_list: options.access_list, }, block.into(), ); diff --git a/src/types/mod.rs b/src/types/mod.rs index 53322a37..1adb09e8 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -40,7 +40,7 @@ pub use self::{ AccountDiff, BlockTrace, ChangedType, Diff, MemoryDiff, StateDiff, StorageDiff, TraceType, TransactionTrace, VMExecutedOperation, VMOperation, VMTrace, }, - transaction::{RawTransaction, Receipt as TransactionReceipt, Transaction}, + transaction::{AccessList, AccessListItem, RawTransaction, Receipt as TransactionReceipt, Transaction}, transaction_id::TransactionId, transaction_request::{CallRequest, TransactionCondition, TransactionRequest}, txpool::{TxpoolContentInfo, TxpoolInspectInfo, TxpoolStatus}, diff --git a/src/types/signed.rs b/src/types/signed.rs index a11f8796..b326489e 100644 --- a/src/types/signed.rs +++ b/src/types/signed.rs @@ -1,4 +1,4 @@ -use crate::types::{Address, Bytes, CallRequest, H256, U256}; +use crate::types::{AccessList, Address, Bytes, CallRequest, H256, U256, U64}; use serde::{Deserialize, Serialize}; /// Struct representing signed data returned from `Accounts::sign` method. @@ -53,6 +53,10 @@ pub struct TransactionParameters { pub data: Bytes, /// The chain ID (None for network ID) pub chain_id: Option, + /// Transaction type, Some(1) for AccessList transaction, None for Legacy + pub transaction_type: Option, + /// Access list + pub access_list: Option, } /// The default fas for transactions. @@ -73,6 +77,8 @@ impl Default for TransactionParameters { value: U256::zero(), data: Bytes::default(), chain_id: None, + transaction_type: None, + access_list: None, } } } @@ -87,6 +93,8 @@ impl From for TransactionParameters { value: call.value.unwrap_or_default(), data: call.data.unwrap_or_default(), chain_id: None, + transaction_type: call.transaction_type, + access_list: call.access_list, } } } @@ -100,6 +108,8 @@ impl Into for TransactionParameters { gas_price: self.gas_price, value: Some(self.value), data: Some(self.data), + transaction_type: self.transaction_type, + access_list: self.access_list, } } } diff --git a/src/types/transaction.rs b/src/types/transaction.rs index 0094b9c4..88fe6a0f 100644 --- a/src/types/transaction.rs +++ b/src/types/transaction.rs @@ -43,6 +43,12 @@ pub struct Transaction { /// Raw transaction data #[serde(default, skip_serializing_if = "Option::is_none")] pub raw: Option, + /// Transaction type, Some(1) for AccessList transaction, None for Legacy + #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")] + pub transaction_type: Option, + /// Access list + #[serde(rename = "accessList", default, skip_serializing_if = "Option::is_none")] + pub access_list: Option, } /// "Receipt" of an executed transaction: details of its execution. @@ -80,6 +86,9 @@ pub struct Receipt { /// Logs bloom #[serde(rename = "logsBloom")] pub logs_bloom: H2048, + /// Transaction type, Some(1) for AccessList transaction, None for Legacy + #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")] + pub transaction_type: Option, } /// Raw bytes of a signed, but not yet sent transaction @@ -91,6 +100,19 @@ pub struct RawTransaction { pub tx: Transaction, } +/// Access list +pub type AccessList = Vec; + +/// Access list item +#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AccessListItem { + /// Accessed address + pub address: H160, + /// Accessed storage keys + pub storage_keys: Vec, +} + #[cfg(test)] mod tests { use super::{RawTransaction, Receipt}; diff --git a/src/types/transaction_request.rs b/src/types/transaction_request.rs index 79a534a5..4cbd8b65 100644 --- a/src/types/transaction_request.rs +++ b/src/types/transaction_request.rs @@ -1,4 +1,4 @@ -use crate::types::{Address, Bytes, U256}; +use crate::types::{AccessList, Address, Bytes, U256, U64}; use serde::{Deserialize, Serialize}; /// Call contract request (eth_call / eth_estimateGas) @@ -27,6 +27,12 @@ pub struct CallRequest { /// Data (None for empty data) #[serde(skip_serializing_if = "Option::is_none")] pub data: Option, + /// Transaction type, Some(1) for AccessList transaction, None for Legacy + #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")] + pub transaction_type: Option, + /// Access list + #[serde(rename = "accessList", default, skip_serializing_if = "Option::is_none")] + pub access_list: Option, } /// Send Transaction Parameters @@ -56,6 +62,12 @@ pub struct TransactionRequest { /// Min block inclusion (None for include immediately) #[serde(skip_serializing_if = "Option::is_none")] pub condition: Option, + /// Transaction type, Some(1) for AccessList transaction, None for Legacy + #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")] + pub transaction_type: Option, + /// Access list + #[serde(rename = "accessList", default, skip_serializing_if = "Option::is_none")] + pub access_list: Option, } /// Represents condition on minimum block number or block timestamp. @@ -85,6 +97,8 @@ mod tests { gas_price: None, value: Some(5_000_000.into()), data: Some(hex!("010203").into()), + transaction_type: None, + access_list: None, }; // when @@ -132,6 +146,8 @@ mod tests { data: Some(hex!("010203").into()), nonce: None, condition: Some(TransactionCondition::Block(5)), + transaction_type: None, + access_list: None, }; // when