1#![cfg_attr(not(feature = "std"), no_std)]
19#![warn(unused_crate_dependencies)]
20
21extern crate alloc;
22
23use alloc::vec::Vec;
24pub use ethereum::{
25 AccessListItem, AuthorizationList, AuthorizationListItem, BlockV3 as Block,
26 LegacyTransactionMessage, Log, ReceiptV4 as Receipt, TransactionAction,
27 TransactionV3 as Transaction,
28};
29use ethereum_types::{H160, H256, U256};
30use fp_evm::{CallOrCreateInfo, CheckEvmTransactionInput};
31use frame_support::dispatch::{DispatchErrorWithPostInfo, PostDispatchInfo};
32use scale_codec::{Decode, Encode};
33
34pub trait ValidatedTransaction {
35 fn apply(
36 source: H160,
37 transaction: Transaction,
38 maybe_force_create_address: Option<H160>,
39 ) -> Result<(PostDispatchInfo, CallOrCreateInfo), DispatchErrorWithPostInfo>;
40}
41
42#[derive(Clone, Debug, Eq, PartialEq, Encode, Decode)]
43pub struct TransactionData {
44 pub action: TransactionAction,
45 pub input: Vec<u8>,
46 pub nonce: U256,
47 pub gas_limit: U256,
48 pub gas_price: Option<U256>,
49 pub max_fee_per_gas: Option<U256>,
50 pub max_priority_fee_per_gas: Option<U256>,
51 pub value: U256,
52 pub chain_id: Option<u64>,
53 pub access_list: Vec<(H160, Vec<H256>)>,
54 pub authorization_list: AuthorizationList,
55}
56
57impl TransactionData {
58 #[allow(clippy::too_many_arguments)]
59 pub fn new(
60 action: TransactionAction,
61 input: Vec<u8>,
62 nonce: U256,
63 gas_limit: U256,
64 gas_price: Option<U256>,
65 max_fee_per_gas: Option<U256>,
66 max_priority_fee_per_gas: Option<U256>,
67 value: U256,
68 chain_id: Option<u64>,
69 access_list: Vec<(H160, Vec<H256>)>,
70 authorization_list: AuthorizationList,
71 ) -> Self {
72 Self {
73 action,
74 input,
75 nonce,
76 gas_limit,
77 gas_price,
78 max_fee_per_gas,
79 max_priority_fee_per_gas,
80 value,
81 chain_id,
82 access_list,
83 authorization_list,
84 }
85 }
86
87 pub fn proof_size_base_cost(&self) -> u64 {
89 self.encode()
90 .len()
91 .saturating_add(65)
93 .saturating_add(1)
95 .saturating_add(1) as u64
97 }
98}
99
100impl From<TransactionData> for CheckEvmTransactionInput {
101 fn from(t: TransactionData) -> Self {
102 CheckEvmTransactionInput {
103 to: if let TransactionAction::Call(to) = t.action {
104 Some(to)
105 } else {
106 None
107 },
108 chain_id: t.chain_id,
109 input: t.input,
110 nonce: t.nonce,
111 gas_limit: t.gas_limit,
112 gas_price: t.gas_price,
113 max_fee_per_gas: t.max_fee_per_gas,
114 max_priority_fee_per_gas: t.max_priority_fee_per_gas,
115 value: t.value,
116 access_list: t.access_list,
117 authorization_list: t
118 .authorization_list
119 .iter()
120 .map(|d| {
121 (
122 d.chain_id.into(),
123 d.address,
124 d.nonce,
125 d.authorizing_address().ok(),
126 )
127 })
128 .collect(),
129 }
130 }
131}
132
133impl From<&Transaction> for TransactionData {
134 fn from(t: &Transaction) -> Self {
135 match t {
136 Transaction::Legacy(t) => TransactionData {
137 action: t.action,
138 input: t.input.clone(),
139 nonce: t.nonce,
140 gas_limit: t.gas_limit,
141 gas_price: Some(t.gas_price),
142 max_fee_per_gas: None,
143 max_priority_fee_per_gas: None,
144 value: t.value,
145 chain_id: t.signature.chain_id(),
146 access_list: Vec::new(),
147 authorization_list: Vec::new(),
148 },
149 Transaction::EIP2930(t) => TransactionData {
150 action: t.action,
151 input: t.input.clone(),
152 nonce: t.nonce,
153 gas_limit: t.gas_limit,
154 gas_price: Some(t.gas_price),
155 max_fee_per_gas: None,
156 max_priority_fee_per_gas: None,
157 value: t.value,
158 chain_id: Some(t.chain_id),
159 access_list: t
160 .access_list
161 .iter()
162 .map(|d| (d.address, d.storage_keys.clone()))
163 .collect(),
164 authorization_list: Vec::new(),
165 },
166 Transaction::EIP1559(t) => TransactionData {
167 action: t.action,
168 input: t.input.clone(),
169 nonce: t.nonce,
170 gas_limit: t.gas_limit,
171 gas_price: None,
172 max_fee_per_gas: Some(t.max_fee_per_gas),
173 max_priority_fee_per_gas: Some(t.max_priority_fee_per_gas),
174 value: t.value,
175 chain_id: Some(t.chain_id),
176 access_list: t
177 .access_list
178 .iter()
179 .map(|d| (d.address, d.storage_keys.clone()))
180 .collect(),
181 authorization_list: Vec::new(),
182 },
183 Transaction::EIP7702(t) => TransactionData {
184 action: t.destination,
185 input: t.data.clone(),
186 nonce: t.nonce,
187 gas_limit: t.gas_limit,
188 gas_price: None,
189 max_fee_per_gas: Some(t.max_fee_per_gas),
190 max_priority_fee_per_gas: Some(t.max_priority_fee_per_gas),
191 value: t.value,
192 chain_id: Some(t.chain_id),
193 access_list: t
194 .access_list
195 .iter()
196 .map(|d| (d.address, d.storage_keys.clone()))
197 .collect(),
198 authorization_list: t.authorization_list.clone(),
199 },
200 }
201 }
202}