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		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	// The transact call wrapped in the extrinsic is part of the PoV, record this as a base cost for the size of the proof.
88	pub fn proof_size_base_cost(&self) -> u64 {
89		self.encode()
90			.len()
91			// signature
92			.saturating_add(65)
93			// pallet index
94			.saturating_add(1)
95			// call index
96			.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}