astar_primitives/
ethereum_checked.rs

1// This file is part of Astar.
2
3// Copyright (C) Stake Technologies Pte.Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later
5
6// Astar is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// Astar is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with Astar. If not, see <http://www.gnu.org/licenses/>.
18
19use parity_scale_codec::{Decode, Encode};
20use scale_info::TypeInfo;
21
22use ethereum::{
23    eip2930::TransactionSignature, AccessListItem, EIP1559Transaction, TransactionAction,
24    TransactionV2 as Transaction,
25};
26use ethereum_types::{H160, H256, U256};
27use frame_support::{pallet_prelude::*, traits::ConstU32, BoundedVec};
28use sp_std::prelude::*;
29
30/// Max Ethereum tx input size: 65_536 bytes
31pub const MAX_ETHEREUM_TX_INPUT_SIZE: u32 = 2u32.pow(16);
32
33pub type EthereumTxInput = BoundedVec<u8, ConstU32<MAX_ETHEREUM_TX_INPUT_SIZE>>;
34
35/// The checked Ethereum transaction. Only contracts `call` is support(no `create`).
36#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, DecodeWithMemTracking)]
37pub struct CheckedEthereumTx {
38    /// Gas limit.
39    pub gas_limit: U256,
40    /// Contract address to call.
41    pub target: H160,
42    /// Amount to transfer.
43    pub value: U256,
44    /// Input of a contract call.
45    pub input: EthereumTxInput,
46    /// Optional access list, specified in EIP-2930.
47    pub maybe_access_list: Option<Vec<(H160, Vec<H256>)>>,
48}
49
50impl CheckedEthereumTx {
51    pub fn into_ethereum_tx(&self, nonce: U256, chain_id: u64) -> Transaction {
52        let access_list = if let Some(ref list) = self.maybe_access_list {
53            list.iter()
54                .map(|(address, storage_keys)| AccessListItem {
55                    address: *address,
56                    storage_keys: storage_keys.clone(),
57                })
58                .collect()
59        } else {
60            Vec::new()
61        };
62
63        Transaction::EIP1559(EIP1559Transaction {
64            chain_id,
65            nonce,
66            max_fee_per_gas: U256::zero(),
67            max_priority_fee_per_gas: U256::zero(),
68            gas_limit: self.gas_limit,
69            value: self.value,
70            action: TransactionAction::Call(self.target),
71            input: self.input.to_vec(),
72            access_list,
73            signature: TransactionSignature::new(true, dummy_rs(), dummy_rs())
74                .expect("dummy signature must be valid"),
75        })
76    }
77}
78
79/// Dummy signature for all transactions.
80fn dummy_rs() -> H256 {
81    H256::from_low_u64_be(1u64)
82}