1use super::common::{
2 compute_v, compute_y_parity, encode_blob_hashes,
3 AbiEncodeResult,
4};
5use alloy::{
6 consensus::{
7 Signed, Transaction as ConsensusTransaction, TxEip1559, TxEip2930,
8 TxEip4844Variant, TxEip7702, TxEnvelope, TxLegacy,
9 }, dyn_abi::DynSolValue, eips::eip7702::SignedAuthorization, primitives::{Address, B256, U256}, rpc::types::{AccessListItem, Transaction, TransactionReceipt}
10};
11
12pub fn encode_transaction_type_0(tx: Transaction, signed_tx: Signed<TxLegacy>) -> Vec<DynSolValue> {
13
14 let signature = signed_tx.signature();
16 let chain_id = tx.chain_id();
17 let v = compute_v(signature, chain_id);
18
19
20
21 let values: Vec<DynSolValue> = vec![
24 DynSolValue::Uint(U256::from(0), 8), DynSolValue::Uint(U256::from(signed_tx.tx().nonce), 64), DynSolValue::Uint(U256::from(signed_tx.tx().gas_price), 128), DynSolValue::Uint(U256::from(signed_tx.tx().gas_limit), 64), DynSolValue::Address(tx.from), DynSolValue::Address(tx.to().unwrap_or(Address::ZERO)), DynSolValue::Uint(tx.value(), 256), DynSolValue::Bytes(tx.input().to_vec()), DynSolValue::Uint(U256::from(v), 256), DynSolValue::FixedBytes(B256::from(signature.r()), 32), DynSolValue::FixedBytes(B256::from(signature.s()), 32) ];
36
37 values
38}
39
40pub fn encode_transaction_type_1(
41 tx: Transaction,
42 signed_tx: Signed<TxEip2930>,
43) -> Vec<DynSolValue> {
44 let signature = signed_tx.signature();
46 let y_parity: u8 = compute_y_parity(signature);
47 let access_list = encode_access_list(signed_tx.tx().access_list.0.clone());
48
49 let values: Vec<DynSolValue> = vec![
50 DynSolValue::Uint(U256::from(1), 8), DynSolValue::Uint(U256::from(signed_tx.tx().chain_id), 64),
52 DynSolValue::Uint(U256::from(signed_tx.tx().nonce), 64), DynSolValue::Uint(U256::from(signed_tx.tx().gas_price), 128), DynSolValue::Uint(U256::from(signed_tx.tx().gas_limit), 64), DynSolValue::Address(tx.from), DynSolValue::Address(tx.to().unwrap_or(Address::ZERO)), DynSolValue::Uint(tx.value(), 256), DynSolValue::Bytes(tx.input().to_vec()), access_list,
60 DynSolValue::Uint(U256::from(y_parity), 8), DynSolValue::FixedBytes(B256::from(signature.r()), 32), DynSolValue::FixedBytes(B256::from(signature.s()), 32), ];
64
65 values
66}
67
68pub fn encode_transaction_type_2(
69 tx: Transaction,
70 signed_tx: Signed<TxEip1559>,
71) -> Vec<DynSolValue> {
72 let signature = signed_tx.signature();
74 let y_parity = compute_y_parity(signature);
75 let access_list = encode_access_list(signed_tx.tx().access_list.0.clone());
76
77 let values: Vec<DynSolValue> = vec![
78 DynSolValue::Uint(U256::from(2), 8),
79 DynSolValue::Uint(U256::from(signed_tx.tx().chain_id), 64),
80 DynSolValue::Uint(U256::from(signed_tx.tx().nonce), 64),
81 DynSolValue::Uint(U256::from(tx.max_priority_fee_per_gas().unwrap_or(0)), 128),
82 DynSolValue::Uint(U256::from(tx.max_fee_per_gas()), 128),
83 DynSolValue::Uint(U256::from(signed_tx.tx().gas_limit), 64),
84 DynSolValue::Address(tx.from),
85 DynSolValue::Address(tx.to().unwrap_or(Address::ZERO)),
86 DynSolValue::Uint(tx.value(), 256),
87 DynSolValue::Bytes(tx.input().to_vec()),
88 access_list,
89 DynSolValue::Uint(U256::from(y_parity), 8),
90 DynSolValue::FixedBytes(B256::from(signature.r()), 32),
91 DynSolValue::FixedBytes(B256::from(signature.s()), 32),
92 ];
93
94 values
95}
96
97pub fn encode_transaction_type_3(
98 tx: Transaction,
99 signed_tx: Signed<TxEip4844Variant>,
100) -> Vec<DynSolValue> {
101 let signature = signed_tx.signature();
103 let y_parity = compute_y_parity(signature);
104
105 let access_list_item_vector = match tx.access_list() {
106 Some(access_list) => access_list.0.clone(),
107 None => Vec::new(),
108 };
109 let access_list = encode_access_list(access_list_item_vector);
110 let blob_version_hashes = tx.blob_versioned_hashes().unwrap_or_default();
111 let blob_hashes = encode_blob_hashes(blob_version_hashes.to_vec());
112
113 let chain_id = tx.chain_id().unwrap_or(0);
116
117 let values: Vec<DynSolValue> = vec![
118 DynSolValue::Uint(U256::from(3), 8),
119 DynSolValue::Uint(U256::from(chain_id), 64),
120 DynSolValue::Uint(U256::from(signed_tx.tx().nonce()), 64),
121 DynSolValue::Uint(U256::from(tx.max_priority_fee_per_gas().unwrap_or(0)), 128),
122 DynSolValue::Uint(U256::from(tx.max_fee_per_gas()), 128),
123 DynSolValue::Uint(U256::from(signed_tx.tx().gas_limit()), 64),
124 DynSolValue::Address(tx.from),
125 DynSolValue::Address(tx.to().unwrap_or(Address::ZERO)),
126 DynSolValue::Uint(tx.value(), 256),
127 DynSolValue::Bytes(tx.input().to_vec()),
128 access_list,
129 DynSolValue::Uint(
130 U256::from(signed_tx.tx().max_fee_per_blob_gas().unwrap_or(0u128)),
131 128,
132 ),
133 blob_hashes,
134 DynSolValue::Uint(U256::from(y_parity), 8),
135 DynSolValue::FixedBytes(B256::from(signature.r()), 32),
136 DynSolValue::FixedBytes(B256::from(signature.s()), 32),
137 ];
138
139 values
140}
141
142pub fn encode_transaction_type_4(
143 tx: Transaction,
144 signed_tx: Signed<TxEip7702>,
145) -> Vec<DynSolValue> {
146 let signature = signed_tx.signature();
148 let y_parity = compute_y_parity(signature);
149 let access_list = encode_access_list(signed_tx.tx().access_list.0.clone());
150 let authorization_list = encode_authorization_list(signed_tx.tx().authorization_list.clone());
151
152 let chain_id = tx.chain_id().unwrap_or(0);
155
156 let values: Vec<DynSolValue> = vec![
157 DynSolValue::Uint(U256::from(3), 8),
158 DynSolValue::Uint(U256::from(chain_id), 64),
159 DynSolValue::Uint(U256::from(signed_tx.tx().nonce()), 64),
160 DynSolValue::Uint(U256::from(tx.max_priority_fee_per_gas().unwrap_or(0)), 128),
161 DynSolValue::Uint(U256::from(tx.max_fee_per_gas()), 128),
162 DynSolValue::Uint(U256::from(signed_tx.tx().gas_limit()), 64),
163 DynSolValue::Address(tx.from),
164 DynSolValue::Address(tx.to().unwrap_or(Address::ZERO)),
165 DynSolValue::Uint(tx.value(), 256),
166 DynSolValue::Bytes(tx.input().to_vec()),
167 access_list,
168 authorization_list,
169 DynSolValue::Uint(U256::from(y_parity), 8),
170 DynSolValue::FixedBytes(B256::from(signature.r()), 32),
171 DynSolValue::FixedBytes(B256::from(signature.s()), 32),
172 ];
173
174 values
175}
176
177pub fn encode_access_list(access_list: Vec<AccessListItem>) -> DynSolValue {
182
183 let mut list = Vec::new();
184 for access_list_item in access_list {
185
186 let mut storage_keys = Vec::new();
187 for storage_item in access_list_item.storage_keys {
188 storage_keys.push(DynSolValue::FixedBytes(storage_item, 32));
189 }
190
191 let access_list_tuple = DynSolValue::Tuple(vec![
193 DynSolValue::Address(access_list_item.address), DynSolValue::Array(storage_keys)
195 ]);
196
197 let access_list_as_bytes = access_list_tuple.abi_encode_packed();
198 list.push(DynSolValue::Bytes(access_list_as_bytes));
199 }
200
201 DynSolValue::Array(list)
203}
204
205pub fn encode_authorization_list(signed_authorizations: Vec<SignedAuthorization>) -> DynSolValue {
206 let mut result = Vec::new();
207 for signed_authorization in signed_authorizations {
208
209 let signed_authorization_tuple = DynSolValue::Tuple(vec![
210 DynSolValue::Uint(U256::from(signed_authorization.chain_id().clone()), 256),
211 DynSolValue::Address(signed_authorization.address().clone()),
212 DynSolValue::Uint(U256::from(signed_authorization.nonce()), 64),
213 DynSolValue::Uint(U256::from(signed_authorization.y_parity()), 8),
214 DynSolValue::Uint(U256::from(signed_authorization.r()), 256),
215 DynSolValue::Uint(U256::from(signed_authorization.s()), 256)
216 ]);
217
218 let pack_encoded = signed_authorization_tuple.abi_encode_packed();
219 result.push(DynSolValue::Bytes(pack_encoded));
220 }
221
222 DynSolValue::Array(result)
223}
224
225pub fn encode_transaction(tx: Transaction) -> Vec<DynSolValue> {
226 match tx.inner.clone() {
227 TxEnvelope::Legacy(signed_tx) => encode_transaction_type_0(tx, signed_tx),
228 TxEnvelope::Eip2930(signed_tx) => encode_transaction_type_1(tx, signed_tx),
229 TxEnvelope::Eip1559(signed_tx) => encode_transaction_type_2(tx, signed_tx),
230 TxEnvelope::Eip4844(signed_tx) => encode_transaction_type_3(tx, signed_tx),
231 TxEnvelope::Eip7702(signed_tx) => encode_transaction_type_4(tx, signed_tx),
232 }
236}
237
238fn encode_receipt(rx: TransactionReceipt) -> Vec<DynSolValue> {
239
240 let log_blooms = rx.inner.logs_bloom().0.to_vec();
245 let result = vec![
246
247 DynSolValue::Uint(U256::from(rx.status()), 8),
249
250 DynSolValue::Uint(U256::from(rx.gas_used), 64),
252
253 DynSolValue::Array(
255 rx.inner.logs().into_iter().map(|log| { let topics = DynSolValue::Array(log.topics().into_iter().map(|topic| {
258 DynSolValue::FixedBytes(topic.clone(), 32)
259 }).collect());
260
261 let log_tuple = DynSolValue::Tuple(vec![
262 DynSolValue::Address(log.address()),
263 topics,
264 DynSolValue::Bytes(log.data().data.to_vec())
265 ]);
266
267 DynSolValue::Bytes(log_tuple.abi_encode_packed())
268 }).collect()
269 ),
270
271 DynSolValue::Bytes(log_blooms),
273 ];
274
275 result
276}
277
278pub fn solidity_packed_encode(
279 tx: Transaction,
280 rx: TransactionReceipt,
281) -> Result<AbiEncodeResult, Box<dyn std::error::Error>> {
282
283 let transaction_fields = encode_transaction(tx);
284 let receipt_fields = encode_receipt(rx);
285 let mut all_fields = Vec::new();
286 all_fields.extend(transaction_fields);
287 all_fields.extend(receipt_fields);
288 let tuple = DynSolValue::Tuple(all_fields.clone());
289 let final_bytes = tuple.abi_encode_packed();
290
291 let field_type: Vec<String> = all_fields.into_iter().map(|field| {
292
293 match field.as_type() {
294 Some(sol_type) => {
295 sol_type.sol_type_name().into_owned()
296 },
297 None => "unknown".into()
298 }
299
300 }).collect();
301
302 Ok(AbiEncodeResult {
303 types: field_type,
304 abi: final_bytes,
305 })
306}