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 0000000000..e93128bb91
Binary files /dev/null and b/tests/ink-contracts/au_ce_getters.wasm differ
diff --git a/tests/integration/ink-contracts/call_xvm_payable.json b/tests/ink-contracts/call_xvm_payable.json
similarity index 100%
rename from tests/integration/ink-contracts/call_xvm_payable.json
rename to tests/ink-contracts/call_xvm_payable.json
diff --git a/tests/integration/ink-contracts/call_xvm_payable.wasm b/tests/ink-contracts/call_xvm_payable.wasm
similarity index 100%
rename from tests/integration/ink-contracts/call_xvm_payable.wasm
rename to tests/ink-contracts/call_xvm_payable.wasm
diff --git a/tests/integration/ink-contracts/dummy_error.json b/tests/ink-contracts/dummy_error.json
similarity index 100%
rename from tests/integration/ink-contracts/dummy_error.json
rename to tests/ink-contracts/dummy_error.json
diff --git a/tests/integration/ink-contracts/dummy_error.wasm b/tests/ink-contracts/dummy_error.wasm
similarity index 100%
rename from tests/integration/ink-contracts/dummy_error.wasm
rename to tests/ink-contracts/dummy_error.wasm
diff --git a/tests/xcm-simulator/fixtures/flipper.json b/tests/ink-contracts/flipper.json
similarity index 100%
rename from tests/xcm-simulator/fixtures/flipper.json
rename to tests/ink-contracts/flipper.json
diff --git a/tests/xcm-simulator/fixtures/flipper.wasm b/tests/ink-contracts/flipper.wasm
similarity index 100%
rename from tests/xcm-simulator/fixtures/flipper.wasm
rename to tests/ink-contracts/flipper.wasm
diff --git a/tests/integration/ink-contracts/payable.json b/tests/ink-contracts/payable.json
similarity index 100%
rename from tests/integration/ink-contracts/payable.json
rename to tests/ink-contracts/payable.json
diff --git a/tests/integration/ink-contracts/payable.wasm b/tests/ink-contracts/payable.wasm
similarity index 100%
rename from tests/integration/ink-contracts/payable.wasm
rename to tests/ink-contracts/payable.wasm
diff --git a/tests/integration/ink-contracts/simple_storage.json b/tests/ink-contracts/simple_storage.json
similarity index 100%
rename from tests/integration/ink-contracts/simple_storage.json
rename to tests/ink-contracts/simple_storage.json
diff --git a/tests/integration/ink-contracts/simple_storage.wasm b/tests/ink-contracts/simple_storage.wasm
similarity index 100%
rename from tests/integration/ink-contracts/simple_storage.wasm
rename to tests/ink-contracts/simple_storage.wasm
diff --git a/tests/integration/Cargo.toml b/tests/integration/Cargo.toml
index 22779b38bc..2295c836a1 100644
--- a/tests/integration/Cargo.toml
+++ b/tests/integration/Cargo.toml
@@ -38,9 +38,11 @@ pallet-evm-precompile-assets-erc20 = { workspace = true }
pallet-evm-precompile-dispatch = { workspace = true }
pallet-unified-accounts = { workspace = true }
precompile-utils = { workspace = true }
+unified-accounts-chain-extension-types = { workspace = true }
astar-primitives = { workspace = true }
astar-runtime = { workspace = true, features = ["std"], optional = true }
+astar-test-utils = { workspace = true, features = ["std"] }
shibuya-runtime = { workspace = true, features = ["std"], optional = true }
shiden-runtime = { workspace = true, features = ["std"], optional = true }
diff --git a/tests/integration/src/account.rs b/tests/integration/src/account.rs
deleted file mode 100644
index 5c1e55a1cb..0000000000
--- a/tests/integration/src/account.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-// 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::*;
-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::