1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
use {
18
    crate::{
19
        xcm_config::{AssetId, ForeignAssetsInstance, XcmConfig},
20
        AccountId, Balances, ForeignAssetsCreator, Runtime,
21
    },
22
    frame_support::{parameter_types, traits::ConstU64},
23
    pallet_evm_precompile_balances_erc20::{Erc20BalancesPrecompile, Erc20Metadata},
24
    pallet_evm_precompile_batch::BatchPrecompile,
25
    pallet_evm_precompile_call_permit::CallPermitPrecompile,
26
    pallet_evm_precompile_modexp::Modexp,
27
    pallet_evm_precompile_proxy::{OnlyIsProxyAndProxy, ProxyPrecompile},
28
    pallet_evm_precompile_sha3fips::Sha3FIPS256,
29
    pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256},
30
    pallet_evm_precompile_xcm::PalletXcmPrecompile,
31
    pallet_evm_precompile_xcm_utils::{AllExceptXcmExecute, XcmUtilsPrecompile},
32
    pallet_evm_precompileset_assets_erc20::Erc20AssetsPrecompileSet,
33
    precompile_utils::precompile_set::{
34
        AcceptDelegateCall, AddressU64, CallableByContract, CallableByPrecompile, OnlyFrom,
35
        PrecompileAt, PrecompileSetBuilder, PrecompileSetStartingWith, PrecompilesInRangeInclusive,
36
        SubcallWithMaxNesting,
37
    },
38
    xcm_primitives::location_matcher::{ForeignAssetMatcher, SingleAddressMatcher},
39
};
40

            
41
/// ERC20 metadata for the native token.
42
pub struct NativeErc20Metadata;
43

            
44
impl Erc20Metadata for NativeErc20Metadata {
45
    /// Returns the name of the token.
46
    fn name() -> &'static str {
47
        "UNIT token"
48
    }
49

            
50
    /// Returns the symbol of the token.
51
    fn symbol() -> &'static str {
52
        "UNIT"
53
    }
54

            
55
    /// Returns the decimals places of the token.
56
    fn decimals() -> u8 {
57
        18
58
    }
59

            
60
    /// Must return `true` only if it represents the main native currency of
61
    /// the network. It must be the currency used in `pallet_evm`.
62
    fn is_native_currency() -> bool {
63
        true
64
    }
65
}
66

            
67
/// The asset precompile address prefix. Addresses that match against this prefix will be routed
68
/// to Erc20AssetsPrecompileSet being marked as foreign
69
pub const FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 18];
70

            
71
/// Const to identify ERC20_BALANCES_PRECOMPILE address
72
pub const ERC20_BALANCES_PRECOMPILE: u64 = 2048;
73

            
74
/// System account size in bytes = Pallet_Name_Hash (16) + Storage_name_hash (16) +
75
/// Blake2_128Concat (16) + AccountId (20) + AccountInfo (4 + 12 + AccountData (4* 16)) = 148
76
pub const SYSTEM_ACCOUNT_SIZE: u64 = 148;
77

            
78
parameter_types! {
79
    pub ForeignAssetPrefix: &'static [u8] = FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX;
80
}
81

            
82
type EthereumPrecompilesChecks = (AcceptDelegateCall, CallableByContract, CallableByPrecompile);
83

            
84
// Pallet-xcm precompile types.
85
// The pallet-balances address is identified by ERC20_BALANCES_PRECOMPILE const
86
type BalancesPrecompileMatch = SingleAddressMatcher<AccountId, ERC20_BALANCES_PRECOMPILE, Balances>;
87

            
88
// Type that matches an AccountId with a foreign asset address (if any)
89
type ForeignAssetMatch = ForeignAssetMatcher<AccountId, AssetId, Runtime, ForeignAssetsCreator>;
90

            
91
#[precompile_utils::precompile_name_from_address]
92
type TemplatePrecompilesAt<R> = (
93
    // Ethereum precompiles:
94
    // Allow DELEGATECALL to stay compliant with Ethereum behavior.
95
    PrecompileAt<AddressU64<1>, ECRecover, EthereumPrecompilesChecks>,
96
    PrecompileAt<AddressU64<2>, Sha256, EthereumPrecompilesChecks>,
97
    PrecompileAt<AddressU64<3>, Ripemd160, EthereumPrecompilesChecks>,
98
    PrecompileAt<AddressU64<4>, Identity, EthereumPrecompilesChecks>,
99
    PrecompileAt<AddressU64<5>, Modexp, EthereumPrecompilesChecks>,
100
    // Non-template specific nor Ethereum precompiles :
101
    PrecompileAt<AddressU64<1024>, Sha3FIPS256, (CallableByContract, CallableByPrecompile)>,
102
    PrecompileAt<AddressU64<1025>, ECRecoverPublicKey, (CallableByContract, CallableByPrecompile)>,
103
    // Template specific precompiles:
104
    PrecompileAt<
105
        AddressU64<ERC20_BALANCES_PRECOMPILE>,
106
        Erc20BalancesPrecompile<R, NativeErc20Metadata, ConstU64<SYSTEM_ACCOUNT_SIZE>>,
107
        (CallableByContract, CallableByPrecompile),
108
    >,
109
    PrecompileAt<AddressU64<2049>, BatchPrecompile<R>, SubcallWithMaxNesting<2>>,
110
    PrecompileAt<
111
        AddressU64<2050>,
112
        CallPermitPrecompile<R>,
113
        (SubcallWithMaxNesting<0>, CallableByContract),
114
    >,
115
    PrecompileAt<
116
        AddressU64<2051>,
117
        XcmUtilsPrecompile<R, XcmConfig, ConstU64<SYSTEM_ACCOUNT_SIZE>>,
118
        CallableByContract<AllExceptXcmExecute<R, XcmConfig, ConstU64<SYSTEM_ACCOUNT_SIZE>>>,
119
    >,
120
    PrecompileAt<
121
        AddressU64<2052>,
122
        PalletXcmPrecompile<R, (BalancesPrecompileMatch, ForeignAssetMatch)>,
123
        (CallableByContract, CallableByPrecompile),
124
    >,
125
    PrecompileAt<
126
        AddressU64<2053>,
127
        ProxyPrecompile<R>,
128
        (
129
            CallableByContract<OnlyIsProxyAndProxy<R>>,
130
            SubcallWithMaxNesting<0>,
131
            // Batch is the only precompile allowed to call Proxy.
132
            CallableByPrecompile<OnlyFrom<AddressU64<2049>>>,
133
        ),
134
    >,
135
);
136

            
137
pub type TemplatePrecompiles<R> = PrecompileSetBuilder<
138
    R,
139
    (
140
        PrecompilesInRangeInclusive<(AddressU64<1>, AddressU64<4095>), TemplatePrecompilesAt<R>>,
141
        // Prefixed precompile sets (XC20)
142
        PrecompileSetStartingWith<
143
            ForeignAssetPrefix,
144
            Erc20AssetsPrecompileSet<R, ForeignAssetsInstance>,
145
            (CallableByContract, CallableByPrecompile),
146
        >,
147
    ),
148
>;