From 1a6f4e22c496f56d9a3055ff5d3b95983d96982a Mon Sep 17 00:00:00 2001 From: Shaun Wang Date: Thu, 12 Oct 2023 23:07:46 +1100 Subject: [PATCH 1/5] Add default account mapping for Wasm contracts. --- Cargo.lock | 1 + chain-extensions/xvm/Cargo.toml | 2 ++ chain-extensions/xvm/src/lib.rs | 29 ++++++++++++++++++++----- runtime/shibuya/src/chain_extensions.rs | 4 ++-- runtime/shibuya/src/lib.rs | 2 +- tests/integration/src/setup.rs | 8 ------- tests/integration/src/xvm.rs | 4 ---- 7 files changed, 30 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2f81d10f4c..d04343ab1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7472,6 +7472,7 @@ dependencies = [ "num-traits", "pallet-contracts", "pallet-contracts-primitives", + "pallet-unified-accounts", "parity-scale-codec", "scale-info", "sp-core", diff --git a/chain-extensions/xvm/Cargo.toml b/chain-extensions/xvm/Cargo.toml index ef28b90dbd..11ac1ed5e1 100644 --- a/chain-extensions/xvm/Cargo.toml +++ b/chain-extensions/xvm/Cargo.toml @@ -15,6 +15,7 @@ log = { workspace = true } num-traits = { workspace = true } pallet-contracts = { workspace = true } pallet-contracts-primitives = { workspace = true } +pallet-unified-accounts = { workspace = true } parity-scale-codec = { workspace = true } scale-info = { workspace = true } sp-core = { workspace = true } @@ -34,6 +35,7 @@ std = [ "num-traits/std", "pallet-contracts/std", "pallet-contracts-primitives/std", + "pallet-unified-accounts/std", "scale-info/std", "sp-std/std", "sp-core/std", diff --git a/chain-extensions/xvm/src/lib.rs b/chain-extensions/xvm/src/lib.rs index b7396a4de9..885e478bf7 100644 --- a/chain-extensions/xvm/src/lib.rs +++ b/chain-extensions/xvm/src/lib.rs @@ -21,8 +21,12 @@ extern crate alloc; use alloc::format; -use astar_primitives::xvm::{Context, VmId, XvmCall}; +use astar_primitives::{ + evm::UnifiedAddressMapper, + xvm::{Context, VmId, XvmCall}, +}; use frame_support::dispatch::Encode; +use frame_system::RawOrigin; use pallet_contracts::chain_extension::{ ChainExtension, Environment, Ext, InitState, RetVal, ReturnFlags, }; @@ -48,18 +52,19 @@ impl TryFrom for XvmFuncId { } /// XVM chain extension. -pub struct XvmExtension(PhantomData<(T, XC)>); +pub struct XvmExtension(PhantomData<(T, XC, UA)>); -impl Default for XvmExtension { +impl Default for XvmExtension { fn default() -> Self { XvmExtension(PhantomData) } } -impl ChainExtension for XvmExtension +impl ChainExtension for XvmExtension where - T: pallet_contracts::Config, + T: pallet_contracts::Config + pallet_unified_accounts::Config, XC: XvmCall, + UA: UnifiedAddressMapper, { fn call(&mut self, env: Environment) -> Result where @@ -89,6 +94,20 @@ where // things on behalf of the caller via XVM. let source = env.ext().address(); + // Claim a default account if needed. + if UA::to_h160(&source).is_none() { + let claim_result = + pallet_unified_accounts::Pallet::::claim_default_evm_address( + RawOrigin::Signed(source.clone()).into(), + ); + if claim_result.is_err() { + return Ok(RetVal::Diverging { + flags: ReturnFlags::REVERT, + data: format!("{:?}", claim_result.err()).into(), + }); + } + } + let xvm_context = Context { source_vm_id: VmId::Wasm, weight_limit, diff --git a/runtime/shibuya/src/chain_extensions.rs b/runtime/shibuya/src/chain_extensions.rs index 9bd7609c5f..db0a59c063 100644 --- a/runtime/shibuya/src/chain_extensions.rs +++ b/runtime/shibuya/src/chain_extensions.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with Astar. If not, see . -use super::{Runtime, Xvm}; +use super::{Runtime, UnifiedAccounts, Xvm}; /// Registered WASM contracts chain extensions. pub use pallet_chain_extension_assets::AssetsExtension; @@ -31,7 +31,7 @@ impl RegisteredChainExtension for DappsStakingExtension { const ID: u16 = 00; } -impl RegisteredChainExtension for XvmExtension { +impl RegisteredChainExtension for XvmExtension { const ID: u16 = 01; } diff --git a/runtime/shibuya/src/lib.rs b/runtime/shibuya/src/lib.rs index f89fa911ba..b4ceb150a9 100644 --- a/runtime/shibuya/src/lib.rs +++ b/runtime/shibuya/src/lib.rs @@ -666,7 +666,7 @@ impl pallet_contracts::Config for Runtime { type WeightInfo = pallet_contracts::weights::SubstrateWeight; type ChainExtension = ( DappsStakingExtension, - XvmExtension, + XvmExtension, AssetsExtension>, ); type Schedule = Schedule; diff --git a/tests/integration/src/setup.rs b/tests/integration/src/setup.rs index d0de6fb599..fe78c0c645 100644 --- a/tests/integration/src/setup.rs +++ b/tests/integration/src/setup.rs @@ -119,14 +119,6 @@ mod shibuya { get_evm_signature(who, secret) )); } - - pub fn claim_default_accounts(account: AccountId) { - let default_h160 = UnifiedAccounts::to_default_h160(&account); - assert_ok!(UnifiedAccounts::claim_default_evm_address( - RuntimeOrigin::signed(account.clone()) - )); - assert_eq!(UnifiedAccounts::to_h160(&account).unwrap(), default_h160); - } } #[cfg(feature = "shiden")] diff --git a/tests/integration/src/xvm.rs b/tests/integration/src/xvm.rs index bf179f5ab5..0ec820dd50 100644 --- a/tests/integration/src/xvm.rs +++ b/tests/integration/src/xvm.rs @@ -330,10 +330,6 @@ fn calling_evm_payable_from_wasm_works() { let wasm_caller_addr = deploy_wasm_contract(CALL_EVM_PAYBLE_NAME); let value = UNIT; - - // claim the default mappings for wasm contract - claim_default_accounts(wasm_caller_addr.clone()); - 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") From e25aad9fd9ddaeadb69e122b7b7c6901660c82ea Mon Sep 17 00:00:00 2001 From: Shaun Wang Date: Thu, 12 Oct 2023 23:48:55 +1100 Subject: [PATCH 2/5] Only map accounts for Wasm if payable call. --- chain-extensions/xvm/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain-extensions/xvm/src/lib.rs b/chain-extensions/xvm/src/lib.rs index 885e478bf7..658f673e20 100644 --- a/chain-extensions/xvm/src/lib.rs +++ b/chain-extensions/xvm/src/lib.rs @@ -95,7 +95,7 @@ where let source = env.ext().address(); // Claim a default account if needed. - if UA::to_h160(&source).is_none() { + if value > 0 && UA::to_h160(&source).is_none() { let claim_result = pallet_unified_accounts::Pallet::::claim_default_evm_address( RawOrigin::Signed(source.clone()).into(), From f2eca1352607d76a159de105b244ce95568c12d7 Mon Sep 17 00:00:00 2001 From: Shaun Wang Date: Fri, 13 Oct 2023 00:43:50 +1100 Subject: [PATCH 3/5] Charge weight for claim default address call. --- chain-extensions/xvm/src/lib.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/chain-extensions/xvm/src/lib.rs b/chain-extensions/xvm/src/lib.rs index 658f673e20..67fa1fabb2 100644 --- a/chain-extensions/xvm/src/lib.rs +++ b/chain-extensions/xvm/src/lib.rs @@ -25,11 +25,12 @@ use astar_primitives::{ evm::UnifiedAddressMapper, xvm::{Context, VmId, XvmCall}, }; -use frame_support::dispatch::Encode; +use frame_support::{dispatch::Encode, weights::Weight}; use frame_system::RawOrigin; use pallet_contracts::chain_extension::{ ChainExtension, Environment, Ext, InitState, RetVal, ReturnFlags, }; +use pallet_unified_accounts::WeightInfo; use sp_runtime::DispatchError; use sp_std::marker::PhantomData; use xvm_chain_extension_types::{XvmCallArgs, XvmExecutionResult}; @@ -92,10 +93,14 @@ where // Similar to EVM behavior, the `source` should be (limited to) the // contract address. Otherwise contracts would be able to do arbitrary // things on behalf of the caller via XVM. - let source = env.ext().address(); + let source = env.ext().address().clone(); // Claim a default account if needed. + let mut actual_weight = Weight::zero(); if value > 0 && UA::to_h160(&source).is_none() { + let weight_of_claim = ::WeightInfo::claim_default_evm_address(); + actual_weight.saturating_accrue(weight_of_claim); + let claim_result = pallet_unified_accounts::Pallet::::claim_default_evm_address( RawOrigin::Signed(source.clone()).into(), @@ -123,13 +128,13 @@ where } } }; - let call_result = - XC::call(xvm_context, vm_id, source.clone(), to, input, value, None); + let call_result = XC::call(xvm_context, vm_id, source, to, input, value, None); - let actual_weight = match call_result { + let used_weight = match call_result { Ok(ref info) => info.used_weight, Err(ref err) => err.used_weight, }; + actual_weight.saturating_accrue(used_weight); env.adjust_weight(charged_weight, actual_weight); match call_result { From e55f316633cce301c089fe1f8831af32d0319272 Mon Sep 17 00:00:00 2001 From: Shaun Wang Date: Fri, 13 Oct 2023 00:44:42 +1100 Subject: [PATCH 4/5] Fix & docs update. --- chain-extensions/xvm/src/lib.rs | 2 +- runtime/local/src/chain_extensions.rs | 4 ++-- runtime/local/src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/chain-extensions/xvm/src/lib.rs b/chain-extensions/xvm/src/lib.rs index 67fa1fabb2..ba1ebcedda 100644 --- a/chain-extensions/xvm/src/lib.rs +++ b/chain-extensions/xvm/src/lib.rs @@ -95,7 +95,7 @@ where // things on behalf of the caller via XVM. let source = env.ext().address().clone(); - // Claim a default account if needed. + // Claim the default evm address if needed. let mut actual_weight = Weight::zero(); if value > 0 && UA::to_h160(&source).is_none() { let weight_of_claim = ::WeightInfo::claim_default_evm_address(); diff --git a/runtime/local/src/chain_extensions.rs b/runtime/local/src/chain_extensions.rs index 9bd7609c5f..db0a59c063 100644 --- a/runtime/local/src/chain_extensions.rs +++ b/runtime/local/src/chain_extensions.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with Astar. If not, see . -use super::{Runtime, Xvm}; +use super::{Runtime, UnifiedAccounts, Xvm}; /// Registered WASM contracts chain extensions. pub use pallet_chain_extension_assets::AssetsExtension; @@ -31,7 +31,7 @@ impl RegisteredChainExtension for DappsStakingExtension { const ID: u16 = 00; } -impl RegisteredChainExtension for XvmExtension { +impl RegisteredChainExtension for XvmExtension { const ID: u16 = 01; } diff --git a/runtime/local/src/lib.rs b/runtime/local/src/lib.rs index b372b6bdbf..6cb0b371ef 100644 --- a/runtime/local/src/lib.rs +++ b/runtime/local/src/lib.rs @@ -844,7 +844,7 @@ impl pallet_contracts::Config for Runtime { type WeightInfo = pallet_contracts::weights::SubstrateWeight; type ChainExtension = ( DappsStakingExtension, - XvmExtension, + XvmExtension, AssetsExtension>, ); type Schedule = Schedule; From 6a58f46c94ad2e8a0038e57379babe987a243359 Mon Sep 17 00:00:00 2001 From: Shaun Wang Date: Fri, 13 Oct 2023 01:04:55 +1100 Subject: [PATCH 5/5] To H160 DB read. --- chain-extensions/xvm/src/lib.rs | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/chain-extensions/xvm/src/lib.rs b/chain-extensions/xvm/src/lib.rs index ba1ebcedda..e86ea687ce 100644 --- a/chain-extensions/xvm/src/lib.rs +++ b/chain-extensions/xvm/src/lib.rs @@ -25,7 +25,7 @@ use astar_primitives::{ evm::UnifiedAddressMapper, xvm::{Context, VmId, XvmCall}, }; -use frame_support::{dispatch::Encode, weights::Weight}; +use frame_support::{dispatch::Encode, traits::Get, weights::Weight}; use frame_system::RawOrigin; use pallet_contracts::chain_extension::{ ChainExtension, Environment, Ext, InitState, RetVal, ReturnFlags, @@ -97,19 +97,24 @@ where // Claim the default evm address if needed. let mut actual_weight = Weight::zero(); - if value > 0 && UA::to_h160(&source).is_none() { - let weight_of_claim = ::WeightInfo::claim_default_evm_address(); - actual_weight.saturating_accrue(weight_of_claim); - - let claim_result = - pallet_unified_accounts::Pallet::::claim_default_evm_address( - RawOrigin::Signed(source.clone()).into(), - ); - if claim_result.is_err() { - return Ok(RetVal::Diverging { - flags: ReturnFlags::REVERT, - data: format!("{:?}", claim_result.err()).into(), - }); + if value > 0 { + // `UA::to_h160` 1 DB read. + actual_weight.saturating_accrue(T::DbWeight::get().reads(1)); + + if UA::to_h160(&source).is_none() { + let weight_of_claim = ::WeightInfo::claim_default_evm_address(); + actual_weight.saturating_accrue(weight_of_claim); + + let claim_result = + pallet_unified_accounts::Pallet::::claim_default_evm_address( + RawOrigin::Signed(source.clone()).into(), + ); + if claim_result.is_err() { + return Ok(RetVal::Diverging { + flags: ReturnFlags::REVERT, + data: format!("{:?}", claim_result.err()).into(), + }); + } } }