fp_ethereum/
lib.rs

1// This file is part of Frontier.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18#![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	) -> Result<(PostDispatchInfo, CallOrCreateInfo), DispatchErrorWithPostInfo>;
39}
40
41#[derive(Clone, Debug, Eq, PartialEq, Encode, Decode)]
42pub struct TransactionData {
43	pub action: TransactionAction,
44	pub input: Vec<u8>,
45	pub nonce: U256,
46	pub gas_limit: U256,
47	pub gas_price: Option<U256>,
48	pub max_fee_per_gas: Option<U256>,
49	pub max_priority_fee_per_gas: Option<U256>,
50	pub value: U256,
51	pub chain_id: Option<u64>,
52	pub access_list: Vec<(H160, Vec<H256>)>,
53	pub authorization_list: AuthorizationList,
54}
55
56impl TransactionData {
57	#[allow(clippy::too_many_arguments)]
58	pub fn new(
59		action: TransactionAction,
60		input: Vec<u8>,
61		nonce: U256,
62		gas_limit: U256,
63		gas_price: Option<U256>,
64		max_fee_per_gas: Option<U256>,
65		max_priority_fee_per_gas: Option<U256>,
66		value: U256,
67		chain_id: Option<u64>,
68		access_list: Vec<(H160, Vec<H256>)>,
69		authorization_list: AuthorizationList,
70	) -> Self {
71		Self {
72			action,
73			input,
74			nonce,
75			gas_limit,
76			gas_price,
77			max_fee_per_gas,
78			max_priority_fee_per_gas,
79			value,
80			chain_id,
81			access_list,
82			authorization_list,
83		}
84	}
85
86	// The transact call wrapped in the extrinsic is part of the PoV, record this as a base cost for the size of the proof.
87	pub fn proof_size_base_cost(&self) -> u64 {
88		self.encode()
89			.len()
90			// signature
91			.saturating_add(65)
92			// pallet index
93			.saturating_add(1)
94			// call index
95			.saturating_add(1) as u64
96	}
97}
98
99impl From<TransactionData> for CheckEvmTransactionInput {
100	fn from(t: TransactionData) -> Self {
101		CheckEvmTransactionInput {
102			to: if let TransactionAction::Call(to) = t.action {
103				Some(to)
104			} else {
105				None
106			},
107			chain_id: t.chain_id,
108			input: t.input,
109			nonce: t.nonce,
110			gas_limit: t.gas_limit,
111			gas_price: t.gas_price,
112			max_fee_per_gas: t.max_fee_per_gas,
113			max_priority_fee_per_gas: t.max_priority_fee_per_gas,
114			value: t.value,
115			access_list: t.access_list,
116			authorization_list: t
117				.authorization_list
118				.iter()
119				.map(|d| {
120					(
121						d.chain_id.into(),
122						d.address,
123						d.nonce,
124						d.authorizing_address().ok(),
125					)
126				})
127				.collect(),
128		}
129	}
130}
131
132impl From<&Transaction> for TransactionData {
133	fn from(t: &Transaction) -> Self {
134		match t {
135			Transaction::Legacy(t) => TransactionData {
136				action: t.action,
137				input: t.input.clone(),
138				nonce: t.nonce,
139				gas_limit: t.gas_limit,
140				gas_price: Some(t.gas_price),
141				max_fee_per_gas: None,
142				max_priority_fee_per_gas: None,
143				value: t.value,
144				chain_id: t.signature.chain_id(),
145				access_list: Vec::new(),
146				authorization_list: Vec::new(),
147			},
148			Transaction::EIP2930(t) => TransactionData {
149				action: t.action,
150				input: t.input.clone(),
151				nonce: t.nonce,
152				gas_limit: t.gas_limit,
153				gas_price: Some(t.gas_price),
154				max_fee_per_gas: None,
155				max_priority_fee_per_gas: None,
156				value: t.value,
157				chain_id: Some(t.chain_id),
158				access_list: t
159					.access_list
160					.iter()
161					.map(|d| (d.address, d.storage_keys.clone()))
162					.collect(),
163				authorization_list: Vec::new(),
164			},
165			Transaction::EIP1559(t) => TransactionData {
166				action: t.action,
167				input: t.input.clone(),
168				nonce: t.nonce,
169				gas_limit: t.gas_limit,
170				gas_price: None,
171				max_fee_per_gas: Some(t.max_fee_per_gas),
172				max_priority_fee_per_gas: Some(t.max_priority_fee_per_gas),
173				value: t.value,
174				chain_id: Some(t.chain_id),
175				access_list: t
176					.access_list
177					.iter()
178					.map(|d| (d.address, d.storage_keys.clone()))
179					.collect(),
180				authorization_list: Vec::new(),
181			},
182			Transaction::EIP7702(t) => TransactionData {
183				action: t.destination,
184				input: t.data.clone(),
185				nonce: t.nonce,
186				gas_limit: t.gas_limit,
187				gas_price: None,
188				max_fee_per_gas: Some(t.max_fee_per_gas),
189				max_priority_fee_per_gas: Some(t.max_priority_fee_per_gas),
190				value: t.value,
191				chain_id: Some(t.chain_id),
192				access_list: t
193					.access_list
194					.iter()
195					.map(|d| (d.address, d.storage_keys.clone()))
196					.collect(),
197				authorization_list: t.authorization_list.clone(),
198			},
199		}
200	}
201}