astar_runtime/
precompiles.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
19//! The Astar Network EVM precompiles. This can be compiled with ``#[no_std]`, ready for Wasm.
20
21use crate::{Runtime, RuntimeCall};
22use astar_primitives::precompiles::DispatchFilterValidate;
23use frame_support::{parameter_types, traits::Contains};
24use pallet_evm_precompile_assets_erc20::Erc20AssetsPrecompileSet;
25use pallet_evm_precompile_blake2::Blake2F;
26use pallet_evm_precompile_bn128::{Bn128Add, Bn128Mul, Bn128Pairing};
27use pallet_evm_precompile_dapp_staking::DappStakingV3Precompile;
28use pallet_evm_precompile_dispatch::Dispatch;
29use pallet_evm_precompile_dispatch_lockdrop::DispatchLockdrop;
30use pallet_evm_precompile_ed25519::Ed25519Verify;
31use pallet_evm_precompile_modexp::Modexp;
32use pallet_evm_precompile_sha3fips::Sha3FIPS256;
33use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256};
34use pallet_evm_precompile_sr25519::Sr25519Precompile;
35use pallet_evm_precompile_substrate_ecdsa::SubstrateEcdsaPrecompile;
36use pallet_evm_precompile_xcm::XcmPrecompile;
37use precompile_utils::precompile_set::*;
38use sp_core::ConstU32;
39use sp_std::fmt::Debug;
40
41/// The asset precompile address prefix. Addresses that match against this prefix will be routed
42/// to Erc20AssetsPrecompileSet
43pub const ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4];
44parameter_types! {
45    pub AssetPrefix: &'static [u8] = ASSET_PRECOMPILE_ADDRESS_PREFIX;
46}
47
48/// Precompile checks for ethereum spec precompiles
49/// We allow DELEGATECALL to stay compliant with Ethereum behavior.
50type EthereumPrecompilesChecks = (AcceptDelegateCall, CallableByContract, CallableByPrecompile);
51
52/// Filter that only allows whitelisted runtime call to pass through dispatch precompile
53pub struct WhitelistedCalls;
54
55impl Contains<RuntimeCall> for WhitelistedCalls {
56    fn contains(t: &RuntimeCall) -> bool {
57        match t {
58            RuntimeCall::Utility(pallet_utility::Call::batch { calls })
59            | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => {
60                calls.iter().all(|call| WhitelistedCalls::contains(call))
61            }
62            RuntimeCall::DappStaking(_) => true,
63            RuntimeCall::Assets(pallet_assets::Call::transfer { .. }) => true,
64            // Governance related calls
65            RuntimeCall::Democracy(_)
66            | RuntimeCall::Treasury(_)
67            | RuntimeCall::CommunityTreasury(_)
68            | RuntimeCall::Preimage(_) => true,
69            _ => false,
70        }
71    }
72}
73
74/// Filter that only allows whitelisted runtime call to pass through dispatch-lockdrop precompile
75pub struct WhitelistedLockdropCalls;
76
77impl Contains<RuntimeCall> for WhitelistedLockdropCalls {
78    fn contains(t: &RuntimeCall) -> bool {
79        match t {
80            RuntimeCall::Utility(pallet_utility::Call::batch { calls })
81            | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => calls
82                .iter()
83                .all(|call| WhitelistedLockdropCalls::contains(call)),
84            RuntimeCall::DappStaking(pallet_dapp_staking::Call::unbond_and_unstake { .. }) => true,
85            RuntimeCall::DappStaking(pallet_dapp_staking::Call::withdraw_unbonded { .. }) => true,
86            RuntimeCall::Balances(pallet_balances::Call::transfer_all { .. }) => true,
87            RuntimeCall::Balances(pallet_balances::Call::transfer_keep_alive { .. }) => true,
88            RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { .. }) => true,
89            RuntimeCall::Assets(pallet_assets::Call::transfer { .. }) => true,
90            _ => false,
91        }
92    }
93}
94
95/// The PrecompileSet installed in the Astar runtime.
96#[precompile_utils::precompile_name_from_address]
97pub type AstarPrecompilesSetAt<R, C> = (
98    // Ethereum precompiles:
99    // We allow DELEGATECALL to stay compliant with Ethereum behavior.
100    PrecompileAt<AddressU64<1>, ECRecover, EthereumPrecompilesChecks>,
101    PrecompileAt<AddressU64<2>, Sha256, EthereumPrecompilesChecks>,
102    PrecompileAt<AddressU64<3>, Ripemd160, EthereumPrecompilesChecks>,
103    PrecompileAt<AddressU64<4>, Identity, EthereumPrecompilesChecks>,
104    PrecompileAt<AddressU64<5>, Modexp, EthereumPrecompilesChecks>,
105    PrecompileAt<AddressU64<6>, Bn128Add, EthereumPrecompilesChecks>,
106    PrecompileAt<AddressU64<7>, Bn128Mul, EthereumPrecompilesChecks>,
107    PrecompileAt<AddressU64<8>, Bn128Pairing, EthereumPrecompilesChecks>,
108    PrecompileAt<AddressU64<9>, Blake2F, EthereumPrecompilesChecks>,
109    // Non-Astar specific nor Ethereum precompiles :
110    PrecompileAt<
111        AddressU64<1024>,
112        Sha3FIPS256<Runtime, ()>,
113        (CallableByContract, CallableByPrecompile),
114    >,
115    PrecompileAt<
116        AddressU64<1025>,
117        Dispatch<R, DispatchFilterValidate<RuntimeCall, WhitelistedCalls>>,
118        // Not callable from smart contract nor precompiles, only EOA accounts
119        // TODO: test this without the gensis hack for blacklisted
120        (),
121    >,
122    PrecompileAt<AddressU64<1026>, ECRecoverPublicKey, (CallableByContract, CallableByPrecompile)>,
123    PrecompileAt<AddressU64<1027>, Ed25519Verify, (CallableByContract, CallableByPrecompile)>,
124    // Astar specific precompiles:
125    PrecompileAt<
126        AddressU64<20481>,
127        DappStakingV3Precompile<R>,
128        (CallableByContract, CallableByPrecompile),
129    >,
130    PrecompileAt<
131        AddressU64<20482>,
132        Sr25519Precompile<R>,
133        (CallableByContract, CallableByPrecompile),
134    >,
135    PrecompileAt<
136        AddressU64<20483>,
137        SubstrateEcdsaPrecompile<R>,
138        (CallableByContract, CallableByPrecompile),
139    >,
140    PrecompileAt<
141        AddressU64<20484>,
142        XcmPrecompile<R, C>,
143        (
144            SubcallWithMaxNesting<1>,
145            CallableByContract,
146            CallableByPrecompile,
147        ),
148    >,
149    // Skipping 20485 and 20486 to make sure all network have consistent
150    // precompiles address
151    PrecompileAt<
152        AddressU64<20487>,
153        DispatchLockdrop<
154            R,
155            DispatchFilterValidate<RuntimeCall, WhitelistedLockdropCalls>,
156            ConstU32<8>,
157        >,
158        // Not callable from smart contract nor precompiled, only EOA accounts
159        (),
160    >,
161);
162
163pub type AstarPrecompiles<R, C> = PrecompileSetBuilder<
164    R,
165    (
166        // Skip precompiles if out of range.
167        PrecompilesInRangeInclusive<
168            // We take range as last precompile index, UPDATE this once new prcompile is added
169            (AddressU64<1>, AddressU64<20487>),
170            AstarPrecompilesSetAt<R, C>,
171        >,
172        // Prefixed precompile sets (XC20)
173        PrecompileSetStartingWith<AssetPrefix, Erc20AssetsPrecompileSet<R>, CallableByContract>,
174    ),
175>;