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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
142
pub type TemplatePrecompiles<R> = PrecompileSetBuilder<
143
    R,
144
    (
145
        PrecompilesInRangeInclusive<(AddressU64<1>, AddressU64<4095>), TemplatePrecompilesAt<R>>,
146
        // Prefixed precompile sets (XC20)
147
        PrecompileSetStartingWith<
148
            ForeignAssetPrefix,
149
            Erc20AssetsPrecompileSet<R, ForeignAssetsInstance>,
150
            (CallableByContract, CallableByPrecompile),
151
        >,
152
    ),
153
>;