From ebbc59d20a90cba74013efaf0066e22dcc89c797 Mon Sep 17 00:00:00 2001 From: Ashutosh Varma Date: Tue, 24 Oct 2023 13:51:22 +0530 Subject: [PATCH] feat(AU): charge storage fee and add initial CE (#1058) * feat: charge storage fee for mappings * feat: add unified account chain extension * feat: add AU CE in Shibuya * feat: add AU CE integration tests * fix: warnings * fix: storage deposit values * fix: integration tests * fix: xcm simulator tests * feat: apply code suggestions * fix: benchmarks * feat: apply code suggestions * feat: update CE interface with `is_mapped` value * feat: apply code suggestions * feat: add enum type and update tests * feat: add docstring in type --- Cargo.lock | 50 ++ Cargo.toml | 5 + .../types/unified-accounts/Cargo.toml | 27 + .../types/unified-accounts/src/lib.rs | 46 ++ chain-extensions/unified-accounts/Cargo.toml | 47 ++ chain-extensions/unified-accounts/src/lib.rs | 104 +++ pallets/unified-accounts/src/benchmarking.rs | 10 + pallets/unified-accounts/src/lib.rs | 30 +- pallets/unified-accounts/src/mock.rs | 3 +- pallets/unified-accounts/src/tests.rs | 37 +- runtime/local/Cargo.toml | 2 + runtime/local/src/chain_extensions.rs | 5 + runtime/local/src/lib.rs | 7 + runtime/shibuya/Cargo.toml | 2 + runtime/shibuya/src/chain_extensions.rs | 5 + runtime/shibuya/src/lib.rs | 7 + .../{integration => }/ink-contracts/README.md | 0 .../async-xcm-call-no-ce.json | 0 .../async-xcm-call-no-ce.wasm | Bin tests/ink-contracts/au_ce_getters.json | 723 ++++++++++++++++++ tests/ink-contracts/au_ce_getters.wasm | Bin 0 -> 19694 bytes .../ink-contracts/call_xvm_payable.json | 0 .../ink-contracts/call_xvm_payable.wasm | Bin .../ink-contracts/dummy_error.json | 0 .../ink-contracts/dummy_error.wasm | Bin .../fixtures => ink-contracts}/flipper.json | 0 .../fixtures => ink-contracts}/flipper.wasm | Bin .../ink-contracts/payable.json | 0 .../ink-contracts/payable.wasm | Bin .../ink-contracts/simple_storage.json | 0 .../ink-contracts/simple_storage.wasm | Bin tests/integration/Cargo.toml | 2 + tests/integration/src/account.rs | 41 - .../src/dispatch_precompile_filter.rs | 2 - tests/integration/src/lib.rs | 4 +- tests/integration/src/setup.rs | 38 +- tests/integration/src/unified_accounts.rs | 119 +++ tests/integration/src/xvm.rs | 9 + tests/utils/Cargo.toml | 29 + tests/utils/src/lib.rs | 117 +++ tests/xcm-simulator/Cargo.toml | 1 + tests/xcm-simulator/fixtures/README.md | 7 - tests/xcm-simulator/src/mocks/mod.rs | 100 +-- tests/xcm-simulator/src/tests/experimental.rs | 21 +- 44 files changed, 1409 insertions(+), 191 deletions(-) create mode 100644 chain-extensions/types/unified-accounts/Cargo.toml create mode 100644 chain-extensions/types/unified-accounts/src/lib.rs create mode 100644 chain-extensions/unified-accounts/Cargo.toml create mode 100644 chain-extensions/unified-accounts/src/lib.rs rename tests/{integration => }/ink-contracts/README.md (100%) rename tests/{xcm-simulator/fixtures => ink-contracts}/async-xcm-call-no-ce.json (100%) rename tests/{xcm-simulator/fixtures => ink-contracts}/async-xcm-call-no-ce.wasm (100%) create mode 100644 tests/ink-contracts/au_ce_getters.json create mode 100644 tests/ink-contracts/au_ce_getters.wasm rename tests/{integration => }/ink-contracts/call_xvm_payable.json (100%) rename tests/{integration => }/ink-contracts/call_xvm_payable.wasm (100%) rename tests/{integration => }/ink-contracts/dummy_error.json (100%) rename tests/{integration => }/ink-contracts/dummy_error.wasm (100%) rename tests/{xcm-simulator/fixtures => ink-contracts}/flipper.json (100%) rename tests/{xcm-simulator/fixtures => ink-contracts}/flipper.wasm (100%) rename tests/{integration => }/ink-contracts/payable.json (100%) rename tests/{integration => }/ink-contracts/payable.wasm (100%) rename tests/{integration => }/ink-contracts/simple_storage.json (100%) rename tests/{integration => }/ink-contracts/simple_storage.wasm (100%) delete mode 100644 tests/integration/src/account.rs create mode 100644 tests/integration/src/unified_accounts.rs create mode 100644 tests/utils/Cargo.toml create mode 100644 tests/utils/src/lib.rs delete mode 100644 tests/xcm-simulator/fixtures/README.md diff --git a/Cargo.lock b/Cargo.lock index 7e0248ec11..7f1416f3a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -634,6 +634,19 @@ dependencies = [ "xcm-executor", ] +[[package]] +name = "astar-test-utils" +version = "0.1.0" +dependencies = [ + "frame-support", + "frame-system", + "pallet-contracts", + "pallet-contracts-primitives", + "parity-scale-codec", + "scale-info", + "sp-runtime", +] + [[package]] name = "async-channel" version = "1.9.0" @@ -4921,6 +4934,7 @@ version = "0.1.0" dependencies = [ "astar-primitives", "astar-runtime", + "astar-test-utils", "env_logger 0.10.0", "fp-evm", "frame-support", @@ -4947,6 +4961,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", + "unified-accounts-chain-extension-types", ] [[package]] @@ -5992,6 +6007,7 @@ dependencies = [ "pallet-block-reward", "pallet-chain-extension-assets", "pallet-chain-extension-dapps-staking", + "pallet-chain-extension-unified-accounts", "pallet-chain-extension-xvm", "pallet-collective", "pallet-contracts", @@ -7458,6 +7474,27 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-chain-extension-unified-accounts" +version = "0.1.0" +dependencies = [ + "astar-primitives", + "frame-support", + "frame-system", + "log", + "num-traits", + "pallet-contracts", + "pallet-contracts-primitives", + "pallet-evm", + "pallet-unified-accounts", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", + "unified-accounts-chain-extension-types", +] + [[package]] name = "pallet-chain-extension-xvm" version = "0.1.1" @@ -13015,6 +13052,7 @@ dependencies = [ "pallet-block-reward", "pallet-chain-extension-assets", "pallet-chain-extension-dapps-staking", + "pallet-chain-extension-unified-accounts", "pallet-chain-extension-xvm", "pallet-collator-selection", "pallet-collective", @@ -15189,6 +15227,17 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "unified-accounts-chain-extension-types" +version = "0.1.0" +dependencies = [ + "num_enum 0.5.11", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", +] + [[package]] name = "universal-hash" version = "0.4.1" @@ -16550,6 +16599,7 @@ name = "xcm-simulator-tests" version = "0.1.0" dependencies = [ "astar-primitives", + "astar-test-utils", "cumulus-pallet-xcm", "frame-support", "frame-system", diff --git a/Cargo.toml b/Cargo.toml index 570b9d2940..4593bcfba4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "runtime/shibuya", "tests/xcm-simulator", "tests/integration", + "tests/utils", "pallets/*", "precompiles/*", @@ -17,6 +18,7 @@ members = [ "chain-extensions/dapps-staking", "chain-extensions/pallet-assets", "chain-extensions/xvm", + "chain-extensions/unified-accounts", "chain-extensions/types/*", "vendor/evm-tracing", @@ -279,6 +281,7 @@ pallet-dynamic-evm-base-fee = { path = "./pallets/dynamic-evm-base-fee", default pallet-unified-accounts = { path = "./pallets/unified-accounts", default-features = false } astar-primitives = { path = "./primitives", default-features = false } +astar-test-utils = { path = "./tests/utils", default-features = false } pallet-evm-precompile-assets-erc20 = { path = "./precompiles/assets-erc20", default-features = false } pallet-evm-precompile-sr25519 = { path = "./precompiles/sr25519", default-features = false } @@ -290,10 +293,12 @@ pallet-evm-precompile-dapps-staking = { path = "./precompiles/dapps-staking", de pallet-chain-extension-dapps-staking = { path = "./chain-extensions/dapps-staking", default-features = false } pallet-chain-extension-xvm = { path = "./chain-extensions/xvm", default-features = false } pallet-chain-extension-assets = { path = "./chain-extensions/pallet-assets", default-features = false } +pallet-chain-extension-unified-accounts = { path = "./chain-extensions/unified-accounts", default-features = false } dapps-staking-chain-extension-types = { path = "./chain-extensions/types/dapps-staking", default-features = false } xvm-chain-extension-types = { path = "./chain-extensions/types/xvm", default-features = false } assets-chain-extension-types = { path = "./chain-extensions/types/assets", default-features = false } +unified-accounts-chain-extension-types = { path = "./chain-extensions/types/unified-accounts", default-features = false } precompile-utils = { path = "./precompiles/utils", default-features = false } diff --git a/chain-extensions/types/unified-accounts/Cargo.toml b/chain-extensions/types/unified-accounts/Cargo.toml new file mode 100644 index 0000000000..340f7195ee --- /dev/null +++ b/chain-extensions/types/unified-accounts/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "unified-accounts-chain-extension-types" +version = "0.1.0" +description = "Types definitions for contracts using Unified Accounts chain-extension." +authors.workspace = true +edition.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +num_enum = { workspace = true } +parity-scale-codec = { workspace = true } +scale-info = { workspace = true } + +#substarte +sp-core = { workspace = true } +sp-runtime = { workspace = true } + +[features] +default = ["std"] +std = [ + "num_enum/std", + "parity-scale-codec/std", + "scale-info/std", + "sp-core/std", + "sp-runtime/std", +] diff --git a/chain-extensions/types/unified-accounts/src/lib.rs b/chain-extensions/types/unified-accounts/src/lib.rs new file mode 100644 index 0000000000..7371e3a9e0 --- /dev/null +++ b/chain-extensions/types/unified-accounts/src/lib.rs @@ -0,0 +1,46 @@ +// This file is part of Astar. + +// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later + +// Astar is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Astar is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Astar. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use num_enum::{IntoPrimitive, TryFromPrimitive}; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; + +#[repr(u16)] +#[derive(TryFromPrimitive, IntoPrimitive, Decode, Encode)] +pub enum Command { + /// Get the mapped Evm address if any + GetEvmAddress = 0, + /// Get the mapped Evm address if any otheriwse default associated Evm address + GetEvmAddressOrDefault = 1, + /// Get the mapped Native address if any + GetNativeAddress = 2, + /// Get the mapped Native address if any otheriwse default associated Native address + GetNativeAddressOrDefault = 3, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, Decode, MaxEncodedLen)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum UnifiedAddress { + /// The address fetched from the mappings and the account + /// is unified + Mapped(T), + /// The default address associated with account as there + /// is no mapping found and accounts are not unified + Default(T), +} diff --git a/chain-extensions/unified-accounts/Cargo.toml b/chain-extensions/unified-accounts/Cargo.toml new file mode 100644 index 0000000000..5f6e4e4b8f --- /dev/null +++ b/chain-extensions/unified-accounts/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "pallet-chain-extension-unified-accounts" +version = "0.1.0" +description = "Chain extension for AU" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +frame-support = { workspace = true } +frame-system = { workspace = true } +log = { workspace = true } +num-traits = { workspace = true } +pallet-contracts = { workspace = true } +pallet-contracts-primitives = { workspace = true } +pallet-evm = { workspace = true } +parity-scale-codec = { workspace = true } +scale-info = { workspace = true } +sp-core = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } + +# Astar +astar-primitives = { workspace = true } +pallet-unified-accounts = { workspace = true } +unified-accounts-chain-extension-types = { workspace = true } + +[features] +default = ["std"] +std = [ + "parity-scale-codec/std", + "frame-support/std", + "frame-system/std", + "num-traits/std", + "pallet-contracts/std", + "pallet-evm/std", + "pallet-contracts-primitives/std", + "scale-info/std", + "sp-std/std", + "sp-core/std", + "sp-runtime/std", + # Astar + "astar-primitives/std", + "pallet-unified-accounts/std", + "unified-accounts-chain-extension-types/std", +] diff --git a/chain-extensions/unified-accounts/src/lib.rs b/chain-extensions/unified-accounts/src/lib.rs new file mode 100644 index 0000000000..17ab43f4e4 --- /dev/null +++ b/chain-extensions/unified-accounts/src/lib.rs @@ -0,0 +1,104 @@ +// This file is part of Astar. + +// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later + +// Astar is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Astar is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Astar. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use astar_primitives::{ + ethereum_checked::AccountMapping, + evm::{EvmAddress, UnifiedAddressMapper}, +}; +use core::marker::PhantomData; +use sp_runtime::DispatchError; + +use frame_support::{traits::Get, DefaultNoBound}; +use pallet_contracts::chain_extension::{ + ChainExtension, Environment, Ext, InitState, Result as DispatchResult, RetVal, +}; +use pallet_evm::AddressMapping; +use parity_scale_codec::Encode; +pub use unified_accounts_chain_extension_types::{ + Command::{self, *}, + UnifiedAddress, +}; + +#[derive(DefaultNoBound)] +pub struct UnifiedAccountsExtension(PhantomData<(T, UA)>); + +impl ChainExtension for UnifiedAccountsExtension +where + T: pallet_contracts::Config + pallet_unified_accounts::Config, + UA: UnifiedAddressMapper, +{ + fn call(&mut self, env: Environment) -> DispatchResult + where + E: Ext, + { + let mut env = env.buf_in_buf_out(); + match env.func_id().try_into().map_err(|_| { + DispatchError::Other("Unsupported func id in Unified Accounts Chain Extension") + })? { + GetEvmAddress => { + let account_id: T::AccountId = env.read_as()?; + + let base_weight = ::DbWeight::get().reads(1); + env.charge_weight(base_weight)?; + // write to buffer + UA::to_h160(&account_id).using_encoded(|r| env.write(r, false, None))?; + } + GetEvmAddressOrDefault => { + let account_id: T::AccountId = env.read_as()?; + + let base_weight = ::DbWeight::get().reads(1); + env.charge_weight(base_weight)?; + + let evm_address = if let Some(h160) = UA::to_h160(&account_id) { + UnifiedAddress::Mapped(h160) + } else { + UnifiedAddress::Default(T::DefaultNativeToEvm::into_h160(account_id)) + }; + // write to buffer + evm_address.using_encoded(|r| env.write(r, false, None))?; + } + GetNativeAddress => { + let evm_address: EvmAddress = env.read_as()?; + + let base_weight = ::DbWeight::get().reads(1); + env.charge_weight(base_weight)?; + // write to buffer + UA::to_account_id(&evm_address).using_encoded(|r| env.write(r, false, None))?; + } + GetNativeAddressOrDefault => { + let evm_address: EvmAddress = env.read_as()?; + + let base_weight = ::DbWeight::get().reads(1); + env.charge_weight(base_weight)?; + + // read the storage item + let native_address = if let Some(native) = UA::to_account_id(&evm_address) { + UnifiedAddress::Mapped(native) + } else { + UnifiedAddress::Default(T::DefaultEvmToNative::into_account_id(evm_address)) + }; + + // write to buffer + native_address.using_encoded(|r| env.write(r, false, None))?; + } + }; + Ok(RetVal::Converging(0)) + } +} diff --git a/pallets/unified-accounts/src/benchmarking.rs b/pallets/unified-accounts/src/benchmarking.rs index a4291e63c3..e1a88290e3 100644 --- a/pallets/unified-accounts/src/benchmarking.rs +++ b/pallets/unified-accounts/src/benchmarking.rs @@ -20,6 +20,7 @@ use super::*; use frame_benchmarking::v2::*; +use frame_support::assert_ok; use frame_system::RawOrigin; /// Assert that the last event equals the provided one. @@ -42,6 +43,10 @@ mod benchmarks { ) .into(); + assert_ok!(T::Currency::mint_into( + &caller, + T::AccountMappingStorageFee::get() + )); let caller_clone = caller.clone(); #[extrinsic_call] @@ -62,6 +67,11 @@ mod benchmarks { let caller_clone = caller.clone(); let evm_address = T::DefaultNativeToEvm::into_h160(caller.clone()); + assert_ok!(T::Currency::mint_into( + &caller, + T::AccountMappingStorageFee::get() + )); + #[extrinsic_call] _(RawOrigin::Signed(caller)); diff --git a/pallets/unified-accounts/src/lib.rs b/pallets/unified-accounts/src/lib.rs index b0ac498832..cb804d2f3b 100644 --- a/pallets/unified-accounts/src/lib.rs +++ b/pallets/unified-accounts/src/lib.rs @@ -39,6 +39,10 @@ //! * `claim_default_evm_address`: Creates the double mapping with default evm address given that //! no prior mapping exists. //! +//! ## Storage Fee +//! User is also charged a storage fee [`AccountMappingStorageFee`](`crate::Config::AccountMappingStorageFee`) +//! before mappings are created to prevent storage abuse. +//! //! WARNINGS: //! * This pallet only handles transfer of native balance only, for the rest of native assets //! hold by evm address like XC20, DAppStaking unclaimed rewards, etc should be transferred @@ -64,12 +68,13 @@ use astar_primitives::{ ethereum_checked::AccountMapping, evm::{EvmAddress, UnifiedAddressMapper}, + Balance, }; use frame_support::{ pallet_prelude::*, traits::{ - fungible::{Inspect, Mutate}, - tokens::{Fortitude::*, Preservation::*}, + fungible::{Inspect as FungibleInspect, Mutate as FungibleMutate}, + tokens::{Fortitude::*, Precision::*, Preservation::*}, IsType, OnKilledAccount, }, }; @@ -109,13 +114,19 @@ pub mod pallet { /// The overarching event type type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// The Currency for managing evm address assets - type Currency: Mutate; + type Currency: FungibleMutate; /// Default evm address to account id conversion type DefaultEvmToNative: AddressMapping; /// Default account id to evm address conversion type DefaultNativeToEvm: AccountMapping; /// EVM chain id + #[pallet::constant] type ChainId: Get; + /// The amount of currency needed for mappings to be added. + /// Two storage items with values sizes, sizeof(AccountId) and sizeof(H160) + /// respectively + #[pallet::constant] + type AccountMappingStorageFee: Get; /// Weight information for the extrinsics in this module type WeightInfo: WeightInfo; } @@ -190,6 +201,9 @@ pub mod pallet { ensure!(evm_address == address, Error::::InvalidSignature); + // charge the storage fee + Self::charge_storage_fee(&who)?; + // Check if the default account id already exists for this evm address let default_account_id = T::DefaultEvmToNative::into_account_id(evm_address.clone()); if frame_system::Pallet::::account_exists(&default_account_id) { @@ -246,6 +260,9 @@ impl Pallet { !EvmToNative::::contains_key(&evm_address), Error::::AlreadyMapped ); + + Self::charge_storage_fee(&account_id)?; + // create double mappings for the pair with default evm address EvmToNative::::insert(&evm_address, &account_id); NativeToEvm::::insert(&account_id, &evm_address); @@ -256,6 +273,11 @@ impl Pallet { }); Ok(evm_address) } + + /// Charge the (exact) storage fee (polietly) from the user and burn it + fn charge_storage_fee(who: &T::AccountId) -> Result { + T::Currency::burn_from(who, T::AccountMappingStorageFee::get(), Exact, Polite) + } } /// EIP-712 compatible signature scheme for verifying ownership of EVM Address @@ -375,7 +397,7 @@ impl AddressMapping for Pallet { pub struct KillAccountMapping(PhantomData); impl OnKilledAccount for KillAccountMapping { fn on_killed_account(who: &T::AccountId) { - // remove mapping created by `claim_account` or `get_or_create_evm_address` + // remove mappings of account reaped if let Some(evm_addr) = NativeToEvm::::take(who) { EvmToNative::::remove(evm_addr); NativeToEvm::::remove(who); diff --git a/pallets/unified-accounts/src/mock.rs b/pallets/unified-accounts/src/mock.rs index 1b0f4a4851..74e60d54b4 100644 --- a/pallets/unified-accounts/src/mock.rs +++ b/pallets/unified-accounts/src/mock.rs @@ -149,7 +149,7 @@ impl pallet_ethereum::Config for TestRuntime { } parameter_types! { - pub TxWeightLimit: Weight = Weight::from_parts(u64::max_value(), 0); + pub const AccountMappingStorageFee: u128 = 100_000_000; } impl pallet_unified_accounts::Config for TestRuntime { @@ -158,6 +158,7 @@ impl pallet_unified_accounts::Config for TestRuntime { type DefaultEvmToNative = HashedAddressMapping; type DefaultNativeToEvm = HashedAccountMapping; type ChainId = ChainId; + type AccountMappingStorageFee = AccountMappingStorageFee; type WeightInfo = (); } diff --git a/pallets/unified-accounts/src/tests.rs b/pallets/unified-accounts/src/tests.rs index be8f9cbe34..d625c1d78e 100644 --- a/pallets/unified-accounts/src/tests.rs +++ b/pallets/unified-accounts/src/tests.rs @@ -144,7 +144,8 @@ fn account_claim_should_work() { ExtBuilder::default().build().execute_with(|| { let alice_eth = UnifiedAccounts::eth_address(&alice_secret()); // default ss58 account associated with eth address - let alice_eth_old_account = ::DefaultEvmToNative::into_account_id(alice_eth.clone()); + let alice_eth_old_account = + ::DefaultEvmToNative::into_account_id(alice_eth.clone()); let signature = get_evm_signature(&ALICE, &alice_secret()); // transfer some funds to alice_eth (H160) @@ -165,21 +166,28 @@ fn account_claim_should_work() { // old account (alice_eth_old_account) assert!(System::events().iter().any(|r| matches!( &r.event, - RuntimeEvent::System(frame_system::Event::KilledAccount { account }) if account == &alice_eth_old_account + RuntimeEvent::System(frame_system::Event::KilledAccount { account }) + if account == &alice_eth_old_account + ))); + + // check if storage fee is charged and burned + assert!(System::events().iter().any(|r| matches!( + &r.event, + RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) + if who == &ALICE && amount == &AccountMappingStorageFee::get() ))); // check for claim account event - System::assert_last_event( - RuntimeEvent::UnifiedAccounts(crate::Event::AccountClaimed { account_id: ALICE.clone(), evm_address: alice_eth.clone()}) - ); + System::assert_last_event(RuntimeEvent::UnifiedAccounts( + crate::Event::AccountClaimed { + account_id: ALICE.clone(), + evm_address: alice_eth.clone(), + }, + )); // make sure mappings are in place - assert_eq!( - EvmToNative::::get(alice_eth).unwrap(), ALICE - ); - assert_eq!( - NativeToEvm::::get(ALICE).unwrap(), alice_eth - ) + assert_eq!(EvmToNative::::get(alice_eth).unwrap(), ALICE); + assert_eq!(NativeToEvm::::get(ALICE).unwrap(), alice_eth) }); } @@ -200,6 +208,13 @@ fn account_default_claim_works() { }, )); + // check if storage fee is charged and burned + assert!(System::events().iter().any(|r| matches!( + &r.event, + RuntimeEvent::Balances(pallet_balances::Event::Burned { who, amount }) + if who == &ALICE && amount == &AccountMappingStorageFee::get() + ))); + // check UnifiedAddressMapper's mapping works assert_eq!( >::to_h160(&ALICE), diff --git a/runtime/local/Cargo.toml b/runtime/local/Cargo.toml index 7727e61bad..36f1c79d38 100644 --- a/runtime/local/Cargo.toml +++ b/runtime/local/Cargo.toml @@ -67,6 +67,7 @@ pallet-transaction-payment-rpc-runtime-api = { workspace = true } astar-primitives = { workspace = true } pallet-block-reward = { workspace = true } pallet-chain-extension-dapps-staking = { workspace = true } +pallet-chain-extension-unified-accounts = { workspace = true } pallet-chain-extension-xvm = { workspace = true } pallet-dapps-staking = { workspace = true } pallet-dynamic-evm-base-fee = { workspace = true } @@ -115,6 +116,7 @@ std = [ "pallet-contracts-primitives/std", "pallet-chain-extension-dapps-staking/std", "pallet-chain-extension-xvm/std", + "pallet-chain-extension-unified-accounts/std", "pallet-dapps-staking/std", "pallet-dynamic-evm-base-fee/std", "pallet-ethereum/std", diff --git a/runtime/local/src/chain_extensions.rs b/runtime/local/src/chain_extensions.rs index db0a59c063..516bc8040b 100644 --- a/runtime/local/src/chain_extensions.rs +++ b/runtime/local/src/chain_extensions.rs @@ -23,6 +23,7 @@ pub use pallet_chain_extension_assets::AssetsExtension; use pallet_contracts::chain_extension::RegisteredChainExtension; pub use pallet_chain_extension_dapps_staking::DappsStakingExtension; +pub use pallet_chain_extension_unified_accounts::UnifiedAccountsExtension; pub use pallet_chain_extension_xvm::XvmExtension; // Following impls defines chain extension IDs. @@ -40,3 +41,7 @@ impl RegisteredChainExten { const ID: u16 = 02; } + +impl RegisteredChainExtension for UnifiedAccountsExtension { + const ID: u16 = 03; +} diff --git a/runtime/local/src/lib.rs b/runtime/local/src/lib.rs index 6cb0b371ef..2df0db9035 100644 --- a/runtime/local/src/lib.rs +++ b/runtime/local/src/lib.rs @@ -507,12 +507,18 @@ impl pallet_utility::Config for Runtime { type WeightInfo = pallet_utility::weights::SubstrateWeight; } +parameter_types! { + // 2 storage items with value size 20 and 32 + pub const AccountMappingStorageFee: u128 = deposit(2, 32 + 20); +} + impl pallet_unified_accounts::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type DefaultEvmToNative = pallet_evm::HashedAddressMapping; type DefaultNativeToEvm = HashedAccountMapping; type ChainId = ChainId; + type AccountMappingStorageFee = AccountMappingStorageFee; type WeightInfo = pallet_unified_accounts::weights::SubstrateWeight; } @@ -846,6 +852,7 @@ impl pallet_contracts::Config for Runtime { DappsStakingExtension, XvmExtension, AssetsExtension>, + UnifiedAccountsExtension, ); type Schedule = Schedule; type AddressGenerator = pallet_contracts::DefaultAddressGenerator; diff --git a/runtime/shibuya/Cargo.toml b/runtime/shibuya/Cargo.toml index f6f158ec9d..9785054da7 100644 --- a/runtime/shibuya/Cargo.toml +++ b/runtime/shibuya/Cargo.toml @@ -97,6 +97,7 @@ orml-xtokens = { workspace = true } astar-primitives = { workspace = true } pallet-block-reward = { workspace = true } pallet-chain-extension-dapps-staking = { workspace = true } +pallet-chain-extension-unified-accounts = { workspace = true } pallet-chain-extension-xvm = { workspace = true } pallet-collator-selection = { workspace = true } pallet-dapps-staking = { workspace = true } @@ -162,6 +163,7 @@ std = [ "pallet-contracts-primitives/std", "pallet-chain-extension-dapps-staking/std", "pallet-chain-extension-xvm/std", + "pallet-chain-extension-unified-accounts/std", "pallet-dynamic-evm-base-fee/std", "pallet-ethereum/std", "pallet-preimage/std", diff --git a/runtime/shibuya/src/chain_extensions.rs b/runtime/shibuya/src/chain_extensions.rs index db0a59c063..516bc8040b 100644 --- a/runtime/shibuya/src/chain_extensions.rs +++ b/runtime/shibuya/src/chain_extensions.rs @@ -23,6 +23,7 @@ pub use pallet_chain_extension_assets::AssetsExtension; use pallet_contracts::chain_extension::RegisteredChainExtension; pub use pallet_chain_extension_dapps_staking::DappsStakingExtension; +pub use pallet_chain_extension_unified_accounts::UnifiedAccountsExtension; pub use pallet_chain_extension_xvm::XvmExtension; // Following impls defines chain extension IDs. @@ -40,3 +41,7 @@ impl RegisteredChainExten { const ID: u16 = 02; } + +impl RegisteredChainExtension for UnifiedAccountsExtension { + const ID: u16 = 03; +} diff --git a/runtime/shibuya/src/lib.rs b/runtime/shibuya/src/lib.rs index b4ceb150a9..86b0048531 100644 --- a/runtime/shibuya/src/lib.rs +++ b/runtime/shibuya/src/lib.rs @@ -668,6 +668,7 @@ impl pallet_contracts::Config for Runtime { DappsStakingExtension, XvmExtension, AssetsExtension>, + UnifiedAccountsExtension, ); type Schedule = Schedule; type AddressGenerator = pallet_contracts::DefaultAddressGenerator; @@ -1203,12 +1204,18 @@ impl pallet_xc_asset_config::Config for Runtime { type WeightInfo = pallet_xc_asset_config::weights::SubstrateWeight; } +parameter_types! { + // 2 storage items with values 20 and 32 + pub const AccountMappingStorageFee: u128 = deposit(2, 32 + 20); +} + impl pallet_unified_accounts::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type DefaultEvmToNative = pallet_evm::HashedAddressMapping; type DefaultNativeToEvm = HashedAccountMapping; type ChainId = EVMChainId; + type AccountMappingStorageFee = AccountMappingStorageFee; type WeightInfo = pallet_unified_accounts::weights::SubstrateWeight; } diff --git a/tests/integration/ink-contracts/README.md b/tests/ink-contracts/README.md similarity index 100% rename from tests/integration/ink-contracts/README.md rename to tests/ink-contracts/README.md diff --git a/tests/xcm-simulator/fixtures/async-xcm-call-no-ce.json b/tests/ink-contracts/async-xcm-call-no-ce.json similarity index 100% rename from tests/xcm-simulator/fixtures/async-xcm-call-no-ce.json rename to tests/ink-contracts/async-xcm-call-no-ce.json diff --git a/tests/xcm-simulator/fixtures/async-xcm-call-no-ce.wasm b/tests/ink-contracts/async-xcm-call-no-ce.wasm similarity index 100% rename from tests/xcm-simulator/fixtures/async-xcm-call-no-ce.wasm rename to tests/ink-contracts/async-xcm-call-no-ce.wasm diff --git a/tests/ink-contracts/au_ce_getters.json b/tests/ink-contracts/au_ce_getters.json new file mode 100644 index 0000000000..d3448d5c79 --- /dev/null +++ b/tests/ink-contracts/au_ce_getters.json @@ -0,0 +1,723 @@ +{ + "source": { + "hash": "0x0cfe2b4d2b98a121c0ce38b07d826f1e4d0c7d9870ff84239cd554b32904617d", + "language": "ink! 4.3.0", + "compiler": "rustc 1.72.0", + "build_info": { + "build_mode": "Debug", + "cargo_contract_version": "3.2.0", + "rust_toolchain": "stable-aarch64-apple-darwin", + "wasm_opt_settings": { + "keep_debug_symbols": true, + "optimization_passes": "Z" + } + } + }, + "contract": { + "name": "au-ce-getters", + "version": "0.1.0", + "authors": [ + "Stake Technologies " + ], + "repository": "https://github.com/AstarNetwork/ink-test-contracts", + "homepage": "https://astar.network/" + }, + "spec": { + "constructors": [ + { + "args": [], + "default": false, + "docs": [], + "label": "new", + "payable": false, + "returnType": { + "displayName": [ + "ink_primitives", + "ConstructorResult" + ], + "type": 0 + }, + "selector": "0x9bae9d5e" + } + ], + "docs": [], + "environment": { + "accountId": { + "displayName": [ + "AccountId" + ], + "type": 3 + }, + "balance": { + "displayName": [ + "Balance" + ], + "type": 16 + }, + "blockNumber": { + "displayName": [ + "BlockNumber" + ], + "type": 19 + }, + "chainExtension": { + "displayName": [ + "ChainExtension" + ], + "type": 20 + }, + "hash": { + "displayName": [ + "Hash" + ], + "type": 17 + }, + "maxEventTopics": 4, + "timestamp": { + "displayName": [ + "Timestamp" + ], + "type": 18 + } + }, + "events": [], + "lang_error": { + "displayName": [ + "ink", + "LangError" + ], + "type": 2 + }, + "messages": [ + { + "args": [ + { + "label": "account_id", + "type": { + "displayName": [ + "AccountId" + ], + "type": 3 + } + } + ], + "default": false, + "docs": [], + "label": "to_h160", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 6 + }, + "selector": "0x0000002a" + }, + { + "args": [ + { + "label": "account_id", + "type": { + "displayName": [ + "AccountId" + ], + "type": 3 + } + } + ], + "default": false, + "docs": [], + "label": "to_h160_or_default", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 10 + }, + "selector": "0x0000002b" + }, + { + "args": [ + { + "label": "evm_address", + "type": { + "displayName": [ + "H160" + ], + "type": 8 + } + } + ], + "default": false, + "docs": [], + "label": "to_account_id", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 12 + }, + "selector": "0x0000002c" + }, + { + "args": [ + { + "label": "evm_address", + "type": { + "displayName": [ + "H160" + ], + "type": 8 + } + } + ], + "default": false, + "docs": [], + "label": "to_account_id_or_default", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 14 + }, + "selector": "0x0000002d" + } + ] + }, + "storage": { + "root": { + "layout": { + "struct": { + "fields": [], + "name": "UAMappingGetter" + } + }, + "root_key": "0x00000000" + } + }, + "types": [ + { + "id": 0, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 1 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 2 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 1 + }, + { + "name": "E", + "type": 2 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 1, + "type": { + "def": { + "tuple": [] + } + } + }, + { + "id": 2, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 1, + "name": "CouldNotReadInput" + } + ] + } + }, + "path": [ + "ink_primitives", + "LangError" + ] + } + }, + { + "id": 3, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 4, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "AccountId" + ] + } + }, + { + "id": 4, + "type": { + "def": { + "array": { + "len": 32, + "type": 5 + } + } + } + }, + { + "id": 5, + "type": { + "def": { + "primitive": "u8" + } + } + }, + { + "id": 6, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 7 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 2 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 7 + }, + { + "name": "E", + "type": 2 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 7, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 0, + "name": "None" + }, + { + "fields": [ + { + "type": 8 + } + ], + "index": 1, + "name": "Some" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 8 + } + ], + "path": [ + "Option" + ] + } + }, + { + "id": 8, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 9, + "typeName": "[u8; 20]" + } + ] + } + }, + "path": [ + "primitive_types", + "H160" + ] + } + }, + { + "id": 9, + "type": { + "def": { + "array": { + "len": 20, + "type": 5 + } + } + } + }, + { + "id": 10, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 11 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 2 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 11 + }, + { + "name": "E", + "type": 2 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 11, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 8, + "typeName": "T" + } + ], + "index": 0, + "name": "Mapped" + }, + { + "fields": [ + { + "type": 8, + "typeName": "T" + } + ], + "index": 1, + "name": "Default" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 8 + } + ], + "path": [ + "unified_accounts_chain_extension_types", + "UnifiedAddress" + ] + } + }, + { + "id": 12, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 13 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 2 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 13 + }, + { + "name": "E", + "type": 2 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 13, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 0, + "name": "None" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Some" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 3 + } + ], + "path": [ + "Option" + ] + } + }, + { + "id": 14, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 15 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 2 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 15 + }, + { + "name": "E", + "type": 2 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 15, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 3, + "typeName": "T" + } + ], + "index": 0, + "name": "Mapped" + }, + { + "fields": [ + { + "type": 3, + "typeName": "T" + } + ], + "index": 1, + "name": "Default" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 3 + } + ], + "path": [ + "unified_accounts_chain_extension_types", + "UnifiedAddress" + ] + } + }, + { + "id": 16, + "type": { + "def": { + "primitive": "u128" + } + } + }, + { + "id": 17, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 4, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "Hash" + ] + } + }, + { + "id": 18, + "type": { + "def": { + "primitive": "u64" + } + } + }, + { + "id": 19, + "type": { + "def": { + "primitive": "u32" + } + } + }, + { + "id": 20, + "type": { + "def": { + "variant": {} + }, + "path": [ + "ink_env", + "types", + "NoChainExtension" + ] + } + } + ], + "version": "4" +} \ No newline at end of file diff --git a/tests/ink-contracts/au_ce_getters.wasm b/tests/ink-contracts/au_ce_getters.wasm new file mode 100644 index 0000000000000000000000000000000000000000..e93128bb916b660f1177837eb25278f5892ae910 GIT binary patch literal 19694 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. - -use crate::setup::*; -pub use sp_io::hashing::keccak_256; - -#[test] -fn transfer_to_h160_via_lookup() { - new_test_ext().execute_with(|| { - let eth_address = H160::from_slice(&keccak_256(b"Alice")[0..20]); - - // make sure account is empty - assert!(EVM::is_account_empty(ð_address)); - - // tranfer to evm account - assert_ok!(Balances::transfer( - RuntimeOrigin::signed(ALICE), - MultiAddress::Address20(eth_address.clone().into()), - UNIT, - )); - - // evm account should have recieved the funds - let (account, _) = EVM::account_basic(ð_address); - assert_eq!(account.balance, (UNIT - ExistentialDeposit::get()).into()); - }); -} diff --git a/tests/integration/src/dispatch_precompile_filter.rs b/tests/integration/src/dispatch_precompile_filter.rs index 1099d592f0..7992b39c0a 100644 --- a/tests/integration/src/dispatch_precompile_filter.rs +++ b/tests/integration/src/dispatch_precompile_filter.rs @@ -187,7 +187,6 @@ fn test_incorrect_dispatch_info_fails() { struct Filter; struct AccountId; enum RuntimeCall { - System, DappsStaking, } impl GetDispatchInfo for RuntimeCall { @@ -204,7 +203,6 @@ fn test_incorrect_dispatch_info_fails() { fn contains(t: &RuntimeCall) -> bool { match t { RuntimeCall::DappsStaking => true, - _ => false, } } } diff --git a/tests/integration/src/lib.rs b/tests/integration/src/lib.rs index d43b845417..012ee39d07 100644 --- a/tests/integration/src/lib.rs +++ b/tests/integration/src/lib.rs @@ -32,7 +32,7 @@ mod assets; #[cfg(feature = "shibuya")] mod xvm; -#[cfg(feature = "shibuya")] -mod account; #[cfg(any(feature = "shibuya", feature = "shiden", feature = "astar"))] mod dispatch_precompile_filter; +#[cfg(feature = "shibuya")] +mod unified_accounts; diff --git a/tests/integration/src/setup.rs b/tests/integration/src/setup.rs index fe78c0c645..7d59f3ac04 100644 --- a/tests/integration/src/setup.rs +++ b/tests/integration/src/setup.rs @@ -35,6 +35,7 @@ pub use shibuya::*; #[cfg(feature = "shibuya")] mod shibuya { use super::*; + use parity_scale_codec::Decode; pub use shibuya_runtime::*; /// 1 SBY. @@ -54,7 +55,7 @@ mod shibuya { ::AddressMapping::into_account_id(address) } - /// Deploy an EVM contract with code. + /// Deploy an EVM contract with code via ALICE as origin. pub fn deploy_evm_contract(code: &str) -> H160 { assert_ok!(EVM::create2( RuntimeOrigin::root(), @@ -79,32 +80,41 @@ mod shibuya { } } - /// Deploy a WASM contract with its name. (The code is in `resource/`.) + /// Deploy a WASM contract via ALICE as origin. (The code is in `../ink-contracts/`.) + /// Assumption: Contract constructor is called "new" and take no arguments pub fn deploy_wasm_contract(name: &str) -> AccountId32 { - let path = format!("ink-contracts/{}.wasm", name); - let code = std::fs::read(path).expect("invalid path"); - let instantiate_result = Contracts::bare_instantiate( + let (address, _) = astar_test_utils::deploy_wasm_contract::( + name, ALICE, 0, Weight::from_parts(10_000_000_000, 1024 * 1024), None, - pallet_contracts_primitives::Code::Upload(code), - // `new` constructor hex::decode("9bae9d5e").expect("invalid data hex"), - vec![], - pallet_contracts::DebugInfo::Skip, - pallet_contracts::CollectEvents::Skip, ); - let address = instantiate_result - .result - .expect("instantiation failed") - .account_id; // On instantiation, the contract got existential deposit. assert_eq!(Balances::free_balance(&address), ExistentialDeposit::get(),); address } + /// Call a wasm smart contract method + pub fn call_wasm_contract_method( + origin: AccountId, + contract_id: AccountId, + data: Vec, + ) -> V { + let (value, _, _) = astar_test_utils::call_wasm_contract_method::( + origin, + contract_id, + 0, + Weight::from_parts(10_000_000_000, 1024 * 1024), + None, + data, + false, + ); + value + } + /// Build the signature payload for given native account and eth private key fn get_evm_signature(who: &AccountId32, secret: &libsecp256k1::SecretKey) -> [u8; 65] { // sign the payload diff --git a/tests/integration/src/unified_accounts.rs b/tests/integration/src/unified_accounts.rs new file mode 100644 index 0000000000..3029f4dbb5 --- /dev/null +++ b/tests/integration/src/unified_accounts.rs @@ -0,0 +1,119 @@ +// This file is part of Astar. + +// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later + +// Astar is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Astar is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Astar. If not, see . + +use crate::setup::*; +use parity_scale_codec::Encode; +use sp_io::hashing::keccak_256; +use unified_accounts_chain_extension_types::UnifiedAddress; + +const AU_CE_GETTER: &'static str = "au_ce_getters"; + +#[test] +fn transfer_to_h160_via_lookup() { + new_test_ext().execute_with(|| { + let eth_address = H160::from_slice(&keccak_256(b"Alice")[0..20]); + + // make sure account is empty + assert!(EVM::is_account_empty(ð_address)); + + // tranfer to evm account + assert_ok!(Balances::transfer( + RuntimeOrigin::signed(ALICE), + MultiAddress::Address20(eth_address.clone().into()), + UNIT, + )); + + // evm account should have recieved the funds + let (account, _) = EVM::account_basic(ð_address); + assert_eq!(account.balance, (UNIT - ExistentialDeposit::get()).into()); + }); +} + +#[test] +fn unified_accounts_chain_extension_works() { + const GET_H160: [u8; 4] = [0x00, 0x00, 0x00, 0x2a]; + const GET_H160_OR_DEFAULT: [u8; 4] = [0x00, 0x00, 0x00, 0x2b]; + const GET_NATIVE: [u8; 4] = [0x00, 0x00, 0x00, 0x2c]; + const GET_NATIVE_OR_DEFAULT: [u8; 4] = [0x00, 0x00, 0x00, 0x2d]; + + new_test_ext().execute_with(|| { + let contract_id = deploy_wasm_contract(AU_CE_GETTER); + + // mapped h160 address should None + assert_eq!( + call_wasm_contract_method::>( + ALICE, + contract_id.clone(), + [GET_H160.to_vec(), ALICE.encode()].concat() + ), + None + ); + // default h160 address should match + assert_eq!( + call_wasm_contract_method::>( + ALICE, + contract_id.clone(), + [GET_H160_OR_DEFAULT.to_vec(), ALICE.encode()].concat() + ), + UnifiedAddress::Default(UnifiedAccounts::to_h160_or_default(&ALICE)) + ); + // mapped native address should be None + assert_eq!( + call_wasm_contract_method::>( + ALICE, + contract_id.clone(), + [GET_NATIVE.to_vec(), alith().encode()].concat() + ), + None + ); + // default native address should match + assert_eq!( + call_wasm_contract_method::>( + ALICE, + contract_id.clone(), + [GET_NATIVE_OR_DEFAULT.to_vec(), alith().encode()].concat() + ), + UnifiedAddress::Default(UnifiedAccounts::to_account_id_or_default(&alith())) + ); + + // + // Create account mappings + // + connect_accounts(&ALICE, &alith_secret_key()); + + // ALICE mapped h160 address should be alith + assert_eq!( + call_wasm_contract_method::>( + ALICE, + contract_id.clone(), + [GET_H160.to_vec(), ALICE.encode()].concat() + ), + Some(alith()) + ); + + // alith mapped native address should ALICE + assert_eq!( + call_wasm_contract_method::>( + ALICE, + contract_id.clone(), + [GET_NATIVE.to_vec(), alith().encode()].concat() + ), + Some(ALICE) + ); + }); +} diff --git a/tests/integration/src/xvm.rs b/tests/integration/src/xvm.rs index 0ec820dd50..cefff28776 100644 --- a/tests/integration/src/xvm.rs +++ b/tests/integration/src/xvm.rs @@ -330,6 +330,15 @@ fn calling_evm_payable_from_wasm_works() { let wasm_caller_addr = deploy_wasm_contract(CALL_EVM_PAYBLE_NAME); let value = UNIT; + + // fund the wasm contract address for paying storage fees for + // AU mappings. + assert_ok!(Balances::transfer_allow_death( + RuntimeOrigin::signed(ALICE), + wasm_caller_addr.clone().into(), + AccountMappingStorageFee::get() + )); + let evm_payable = evm_payable_callee_addr.as_ref().to_vec(); let deposit_func = hex::decode("d0e30db0").expect("invalid deposit function hex"); let input = hex::decode("0000002a") diff --git a/tests/utils/Cargo.toml b/tests/utils/Cargo.toml new file mode 100644 index 0000000000..0421e99221 --- /dev/null +++ b/tests/utils/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "astar-test-utils" +version = "0.1.0" +description = "Astar test utils" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +parity-scale-codec = { workspace = true } +scale-info = { workspace = true } + +# Base functionality +frame-support = { workspace = true } +frame-system = { workspace = true } +pallet-contracts = { workspace = true } +pallet-contracts-primitives = { workspace = true } +sp-runtime = { workspace = true } + +[features] +default = ["std"] +std = [ + "parity-scale-codec/std", + "frame-support/std", + "frame-system/std", + "pallet-contracts/std", + "pallet-contracts-primitives/std", +] diff --git a/tests/utils/src/lib.rs b/tests/utils/src/lib.rs new file mode 100644 index 0000000000..ad84cc9167 --- /dev/null +++ b/tests/utils/src/lib.rs @@ -0,0 +1,117 @@ +// This file is part of Astar. + +// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later + +// Astar is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Astar is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Astar. If not, see . + +use frame_support::{traits::Currency, weights::Weight}; +use pallet_contracts_primitives::{Code, ReturnFlags}; +use parity_scale_codec::Decode; +use sp_runtime::traits::Hash; + +type ContractBalanceOf = <::Currency as Currency< + ::AccountId, +>>::Balance; + +/// Load a given wasm module from wasm binary contents along +/// with it's hash. +/// +/// The fixture files are located under the `../ink-contracts/` directory. +pub fn load_wasm_module( + fixture_name: &str, +) -> std::io::Result<(Vec, ::Output)> +where + T: frame_system::Config, +{ + let fixture_path = ["../ink-contracts/", fixture_name, ".wasm"].concat(); + let wasm_binary = std::fs::read(fixture_path)?; + let code_hash = T::Hashing::hash(&wasm_binary); + Ok((wasm_binary, code_hash)) +} + +// Load and deploy the contract from wasm binary +/// and check for successful deploy +pub fn deploy_wasm_contract( + contract_name: &str, + origin: T::AccountId, + value: ContractBalanceOf, + gas_limit: Weight, + storage_deposit_limit: Option>, + data: Vec, +) -> (T::AccountId, ::Output) { + let (code, hash) = load_wasm_module::(contract_name).unwrap(); + let outcome = pallet_contracts::Pallet::::bare_instantiate( + origin, + value, + gas_limit, + storage_deposit_limit, + Code::Upload(code), + data, + vec![], + pallet_contracts::DebugInfo::Skip, + pallet_contracts::CollectEvents::Skip, + ); + + // make sure it does not revert + let result = outcome.result.unwrap(); + assert!( + !result.result.did_revert(), + "deploy_contract: reverted - {:?}", + result + ); + (result.account_id, hash) +} + +/// Call the wasm contract method and returns the decoded return +/// values along with return flags and consumed weight +pub fn call_wasm_contract_method( + origin: T::AccountId, + dest: T::AccountId, + value: ContractBalanceOf, + gas_limit: Weight, + storage_deposit_limit: Option>, + data: Vec, + debug: bool, +) -> (V, ReturnFlags, Weight) { + let outcome = pallet_contracts::Pallet::::bare_call( + origin, + dest, + value, + gas_limit, + storage_deposit_limit, + data, + pallet_contracts::DebugInfo::Skip, + pallet_contracts::CollectEvents::Skip, + pallet_contracts::Determinism::Enforced, + ); + + if debug { + println!( + "Contract debug buffer - {:?}", + String::from_utf8(outcome.debug_message.clone()) + ); + println!("Contract outcome - {outcome:?}"); + } + + let res = outcome.result.unwrap(); + // check for revert + assert!(!res.did_revert(), "Contract reverted!"); + + let value = Result::::decode(&mut res.data.as_ref()) + .expect("decoding failed") + .expect("ink! lang error"); + + (value, res.flags, outcome.gas_consumed) +} diff --git a/tests/xcm-simulator/Cargo.toml b/tests/xcm-simulator/Cargo.toml index 3acbe7fbf2..0b784de7d4 100644 --- a/tests/xcm-simulator/Cargo.toml +++ b/tests/xcm-simulator/Cargo.toml @@ -32,6 +32,7 @@ sp-tracing = { workspace = true } # Custom Astar inclusions astar-primitives = { workspace = true } +astar-test-utils = { workspace = true } pallet-dapps-staking = { workspace = true } pallet-xc-asset-config = { workspace = true } diff --git a/tests/xcm-simulator/fixtures/README.md b/tests/xcm-simulator/fixtures/README.md deleted file mode 100644 index 5c71d97488..0000000000 --- a/tests/xcm-simulator/fixtures/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## fixtures -This directory contains contracts which are used in experimental scenarios. - -Files in this directory are used by experimental scenarios in `src/experimental.rs`. The json -files are for informational purposes only and are not consumed by the tests. - -The source code for the contracts can be found at https://github.com/AstarNetwork/ink-test-contracts diff --git a/tests/xcm-simulator/src/mocks/mod.rs b/tests/xcm-simulator/src/mocks/mod.rs index 211789d55d..e8ea59983c 100644 --- a/tests/xcm-simulator/src/mocks/mod.rs +++ b/tests/xcm-simulator/src/mocks/mod.rs @@ -21,19 +21,12 @@ pub(crate) mod parachain; pub(crate) mod relay_chain; use frame_support::traits::{Currency, IsType, OnFinalize, OnInitialize}; -use frame_support::weights::Weight; -use pallet_contracts_primitives::{Code, ReturnFlags}; -use parity_scale_codec::Decode; -use sp_runtime::traits::{Bounded, Hash, StaticLookup}; +use sp_runtime::traits::{Bounded, StaticLookup}; use sp_runtime::DispatchResult; use xcm::latest::prelude::*; use xcm_executor::traits::Convert; use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt}; -type ContractBalanceOf = <::Currency as Currency< - ::AccountId, ->>::Balance; - pub const ALICE: sp_runtime::AccountId32 = sp_runtime::AccountId32::new([0xFAu8; 32]); pub const BOB: sp_runtime::AccountId32 = sp_runtime::AccountId32::new([0xFBu8; 32]); pub const INITIAL_BALANCE: u128 = 1_000_000_000_000_000_000_000_000; @@ -260,94 +253,3 @@ where units_per_second.unwrap_or(1_000_000_000_000), ) } - -/// Load a given wasm module from wasm binary contents along -/// with it's hash. -/// -/// The fixture files are located under the `fixtures/` directory. -pub fn load_module( - fixture_name: &str, -) -> std::io::Result<(Vec, ::Output)> -where - T: frame_system::Config, -{ - let fixture_path = ["fixtures/", fixture_name, ".wasm"].concat(); - let wasm_binary = std::fs::read(fixture_path)?; - let code_hash = T::Hashing::hash(&wasm_binary); - Ok((wasm_binary, code_hash)) -} - -/// Load and deploy the contract from wasm binary -/// and check for successful deploy -pub fn deploy_contract( - contract_name: &str, - origin: T::AccountId, - value: ContractBalanceOf, - gas_limit: Weight, - storage_deposit_limit: Option>, - data: Vec, -) -> (T::AccountId, ::Output) { - let (code, hash) = load_module::(contract_name).unwrap(); - let outcome = pallet_contracts::Pallet::::bare_instantiate( - origin, - value, - gas_limit, - storage_deposit_limit, - Code::Upload(code), - data, - vec![], - pallet_contracts::DebugInfo::Skip, - pallet_contracts::CollectEvents::Skip, - ); - - // make sure it does not revert - let result = outcome.result.unwrap(); - assert!( - !result.result.did_revert(), - "deploy_contract: reverted - {:?}", - result - ); - (result.account_id, hash) -} - -/// Call the wasm contract method and returns the decoded return -/// values along with return flags and consumed weight -pub fn call_contract_method( - origin: T::AccountId, - dest: T::AccountId, - value: ContractBalanceOf, - gas_limit: Weight, - storage_deposit_limit: Option>, - data: Vec, - debug: bool, -) -> (V, ReturnFlags, Weight) { - let outcome = pallet_contracts::Pallet::::bare_call( - origin, - dest, - value, - gas_limit, - storage_deposit_limit, - data, - pallet_contracts::DebugInfo::Skip, - pallet_contracts::CollectEvents::Skip, - pallet_contracts::Determinism::Enforced, - ); - - if debug { - println!( - "Contract debug buffer - {:?}", - String::from_utf8(outcome.debug_message.clone()) - ); - println!("Contract outcome - {outcome:?}"); - } - - let res = outcome.result.unwrap(); - // check for revert - assert!(!res.did_revert(), "Contract reverted!"); - - ( - V::decode(&mut res.data.as_ref()).unwrap(), - res.flags, - outcome.gas_consumed, - ) -} diff --git a/tests/xcm-simulator/src/tests/experimental.rs b/tests/xcm-simulator/src/tests/experimental.rs index 6665d17efc..bf0d706864 100644 --- a/tests/xcm-simulator/src/tests/experimental.rs +++ b/tests/xcm-simulator/src/tests/experimental.rs @@ -22,6 +22,7 @@ use crate::mocks::{ *, }; +use astar_test_utils::{call_wasm_contract_method, deploy_wasm_contract}; use frame_support::{assert_ok, weights::Weight}; use parity_scale_codec::Encode; use sp_runtime::traits::Bounded; @@ -171,7 +172,7 @@ fn xcm_remote_transact_contract() { // deploy and initialize flipper contract with `true` in ParaA let mut contract_id = [0u8; 32].into(); ParaA::execute_with(|| { - (contract_id, _) = deploy_contract::( + (contract_id, _) = deploy_wasm_contract::( "flipper", ALICE.into(), 0, @@ -182,7 +183,7 @@ fn xcm_remote_transact_contract() { ); // check for flip status - let (res, _, _) = call_contract_method::>( + let (res, _, _) = call_wasm_contract_method::( ALICE.into(), contract_id.clone(), 0, @@ -191,7 +192,7 @@ fn xcm_remote_transact_contract() { SELECTOR_GET.to_vec(), true, ); - assert_eq!(res, Ok(true)); + assert_eq!(res, true); }); ParaB::execute_with(|| { @@ -228,7 +229,7 @@ fn xcm_remote_transact_contract() { // check for flip status, it should be false ParaA::execute_with(|| { - let (res, _, _) = call_contract_method::>( + let (res, _, _) = call_wasm_contract_method::( ALICE.into(), contract_id.clone(), 0, @@ -237,7 +238,7 @@ fn xcm_remote_transact_contract() { SELECTOR_GET.to_vec(), true, ); - assert_eq!(res, Ok(false)); + assert_eq!(res, false); }); } @@ -273,7 +274,7 @@ fn test_async_xcm_contract_call_no_ce() { // let contract_id = ParaA::execute_with(|| { // deploy contract - let (contract_id, _) = deploy_contract::( + let (contract_id, _) = deploy_wasm_contract::( "async-xcm-call-no-ce", ALICE.into(), 0, @@ -309,7 +310,7 @@ fn test_async_xcm_contract_call_no_ce() { // ParaA::execute_with(|| { assert_eq!( - call_contract_method::>( + call_wasm_contract_method::( ALICE.into(), contract_id.clone(), 0, @@ -342,7 +343,7 @@ fn test_async_xcm_contract_call_no_ce() { true, ) .0, - Ok(true) + true ); }); @@ -359,7 +360,7 @@ fn test_async_xcm_contract_call_no_ce() { // Check for contract method called ParaA::execute_with(|| { assert_eq!( - call_contract_method::, ()>>( + call_wasm_contract_method::>( ALICE.into(), contract_id.clone(), 0, @@ -369,7 +370,7 @@ fn test_async_xcm_contract_call_no_ce() { true, ) .0, - Ok(Some(true)) + Some(true) ); }); }