From 87a6e9537d374edf8072f7758fe7616a4a1dfe61 Mon Sep 17 00:00:00 2001 From: Ashutosh Varma Date: Tue, 12 Sep 2023 10:05:31 +0200 Subject: [PATCH 01/15] feat: disable all in dispatch precompile --- Cargo.lock | 1 + primitives/Cargo.toml | 2 ++ primitives/src/lib.rs | 3 +++ primitives/src/precompiles.rs | 38 ++++++++++++++++++++++++++++++ runtime/astar/src/precompiles.rs | 5 ++-- runtime/local/src/precompiles.rs | 5 ++-- runtime/shibuya/src/precompiles.rs | 5 ++-- runtime/shiden/src/precompiles.rs | 5 ++-- 8 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 primitives/src/precompiles.rs diff --git a/Cargo.lock b/Cargo.lock index 28f586a9b..4fc78e125 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -519,6 +519,7 @@ dependencies = [ "pallet-assets", "pallet-evm", "pallet-evm-precompile-assets-erc20", + "pallet-evm-precompile-dispatch", "pallet-xc-asset-config", "parity-scale-codec", "scale-info", diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 8f0effb94..48b8e9fd0 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -39,6 +39,7 @@ pallet-evm = { workspace = true } # Astar pallets & dependencies pallet-evm-precompile-assets-erc20 = { workspace = true } +pallet-evm-precompile-dispatch = { workspace = true } pallet-xc-asset-config = { workspace = true } [features] @@ -64,5 +65,6 @@ std = [ "pallet-assets/std", "pallet-evm/std", "pallet-evm-precompile-assets-erc20/std", + "pallet-evm-precompile-dispatch/std" ] runtime-benchmarks = ["xcm-builder/runtime-benchmarks", "pallet-assets/runtime-benchmarks"] diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 9cf71cb37..010feba29 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -32,6 +32,9 @@ pub mod xvm; /// EVM primitives. pub mod evm; +/// Precompiles +pub mod precompiles; + /// Benchmark primitives #[cfg(feature = "runtime-benchmarks")] pub mod benchmarks; diff --git a/primitives/src/precompiles.rs b/primitives/src/precompiles.rs new file mode 100644 index 000000000..2c80ff786 --- /dev/null +++ b/primitives/src/precompiles.rs @@ -0,0 +1,38 @@ +// 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 fp_evm::{ExitError, PrecompileFailure}; +use pallet_evm_precompile_dispatch::DispatchValidateT; + +pub struct BlockAllDispatchValidate; + +/// The default implementation of `DispatchValidateT`. +impl DispatchValidateT + for BlockAllDispatchValidate +{ + fn validate_before_dispatch( + _origin: &AccountId, + _call: &RuntimeCall, + ) -> Option { + Some(PrecompileFailure::Error { + exit_status: ExitError::Other("invalid call".into()), + }) + } +} diff --git a/runtime/astar/src/precompiles.rs b/runtime/astar/src/precompiles.rs index cc0d81180..28d3b7b91 100644 --- a/runtime/astar/src/precompiles.rs +++ b/runtime/astar/src/precompiles.rs @@ -18,6 +18,7 @@ //! The Astar Network EVM precompiles. This can be compiled with ``#[no_std]`, ready for Wasm. +use astar_primitives::precompiles::BlockAllDispatchValidate; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -74,7 +75,7 @@ where DappsStakingWrapper: Precompile, BatchPrecompile: Precompile, XcmPrecompile: Precompile, - Dispatch: Precompile, + Dispatch: Precompile, R: pallet_evm::Config + pallet_assets::Config + pallet_xcm::Config @@ -106,7 +107,7 @@ where a if a == hash(9) => Some(Blake2F::execute(handle)), // nor Ethereum precompiles : a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), - a if a == hash(1025) => Some(Dispatch::::execute(handle)), + a if a == hash(1025) => Some(Dispatch::::execute(handle)), a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(1027) => Some(Ed25519Verify::execute(handle)), // Astar precompiles (starts from 0x5000): diff --git a/runtime/local/src/precompiles.rs b/runtime/local/src/precompiles.rs index 8520a7522..180f3866d 100644 --- a/runtime/local/src/precompiles.rs +++ b/runtime/local/src/precompiles.rs @@ -18,6 +18,7 @@ //! The Local EVM precompiles. This can be compiled with ``#[no_std]`, ready for Wasm. +use astar_primitives::precompiles::BlockAllDispatchValidate; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -72,7 +73,7 @@ where DappsStakingWrapper: Precompile, BatchPrecompile: Precompile, XvmPrecompile>: Precompile, - Dispatch: Precompile, + Dispatch: Precompile, R: pallet_evm::Config + pallet_xvm::Config + pallet_assets::Config @@ -103,7 +104,7 @@ where a if a == hash(9) => Some(Blake2F::execute(handle)), // nor Ethereum precompiles : a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), - a if a == hash(1025) => Some(Dispatch::::execute(handle)), + a if a == hash(1025) => Some(Dispatch::::execute(handle)), a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(1027) => Some(Ed25519Verify::execute(handle)), // Astar precompiles (starts from 0x5000): diff --git a/runtime/shibuya/src/precompiles.rs b/runtime/shibuya/src/precompiles.rs index 3761e33ff..b572c1997 100644 --- a/runtime/shibuya/src/precompiles.rs +++ b/runtime/shibuya/src/precompiles.rs @@ -18,6 +18,7 @@ //! The Shibuya Network EVM precompiles. This can be compiled with ``#[no_std]`, ready for Wasm. +use astar_primitives::precompiles::BlockAllDispatchValidate; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -77,7 +78,7 @@ where XcmPrecompile: Precompile, BatchPrecompile: Precompile, XvmPrecompile>: Precompile, - Dispatch: Precompile, + Dispatch: Precompile, R: pallet_evm::Config + pallet_assets::Config + pallet_xcm::Config @@ -110,7 +111,7 @@ where a if a == hash(9) => Some(Blake2F::execute(handle)), // nor Ethereum precompiles : a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), - a if a == hash(1025) => Some(Dispatch::::execute(handle)), + a if a == hash(1025) => Some(Dispatch::::execute(handle)), a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(1027) => Some(Ed25519Verify::execute(handle)), // Astar precompiles (starts from 0x5000): diff --git a/runtime/shiden/src/precompiles.rs b/runtime/shiden/src/precompiles.rs index 62b1023e5..5594b2494 100644 --- a/runtime/shiden/src/precompiles.rs +++ b/runtime/shiden/src/precompiles.rs @@ -18,6 +18,7 @@ //! The Shiden Network EVM precompiles. This can be compiled with ``#[no_std]`, ready for Wasm. +use astar_primitives::precompiles::BlockAllDispatchValidate; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -74,7 +75,7 @@ where DappsStakingWrapper: Precompile, BatchPrecompile: Precompile, XcmPrecompile: Precompile, - Dispatch: Precompile, + Dispatch: Precompile, R: pallet_evm::Config + pallet_assets::Config + pallet_xcm::Config @@ -106,7 +107,7 @@ where a if a == hash(9) => Some(Blake2F::execute(handle)), // nor Ethereum precompiles : a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), - a if a == hash(1025) => Some(Dispatch::::execute(handle)), + a if a == hash(1025) => Some(Dispatch::::execute(handle)), a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(1027) => Some(Ed25519Verify::execute(handle)), // Astar precompiles (starts from 0x5000): From 73e53bc9ca6492704eedb532115051e5a03e1d4e Mon Sep 17 00:00:00 2001 From: Deepanshu Hooda Date: Wed, 13 Sep 2023 16:50:58 +0200 Subject: [PATCH 02/15] taplo fix --- primitives/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 48b8e9fd0..737ff4306 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -65,6 +65,6 @@ std = [ "pallet-assets/std", "pallet-evm/std", "pallet-evm-precompile-assets-erc20/std", - "pallet-evm-precompile-dispatch/std" + "pallet-evm-precompile-dispatch/std", ] runtime-benchmarks = ["xcm-builder/runtime-benchmarks", "pallet-assets/runtime-benchmarks"] From d7446308bffff551703e1593b10468e9e82eebc9 Mon Sep 17 00:00:00 2001 From: Deepanshu Hooda Date: Thu, 14 Sep 2023 17:11:13 +0200 Subject: [PATCH 03/15] add DispatchPrecompileFilter --- tests/integration/src/dispatch_filter.rs | 35 ++++++++++++++++++++++++ tests/integration/src/lib.rs | 3 ++ 2 files changed, 38 insertions(+) create mode 100644 tests/integration/src/dispatch_filter.rs diff --git a/tests/integration/src/dispatch_filter.rs b/tests/integration/src/dispatch_filter.rs new file mode 100644 index 000000000..3da2deaca --- /dev/null +++ b/tests/integration/src/dispatch_filter.rs @@ -0,0 +1,35 @@ +// 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(test)] + +use crate::setup::*; +use frame_support::traits::InstanceFilter; + +#[test] +fn filter_accepts_batch_call_with_dappsstaking() { + ExtBuilder::default().build().execute_with(|| { + let contract = SmartContract::Evm(H160::repeat_byte(0x01)); + let inner_call = RuntimeCall::DappsStaking(DappStakingCall::Call::claim_staker{ + contract_id : contract.clone(), + }); + let call = RuntimeCall::Utility(UtilityCall::batch { + calls : vec![inner_call] + }); + assert!(DispatchPrecompileFilter.filter(&call)); + }); +} \ No newline at end of file diff --git a/tests/integration/src/lib.rs b/tests/integration/src/lib.rs index c36fc93ed..bbbdae52b 100644 --- a/tests/integration/src/lib.rs +++ b/tests/integration/src/lib.rs @@ -31,3 +31,6 @@ mod assets; #[cfg(feature = "shibuya")] mod xvm; + +#[cfg(feature = "shibuya")] +mod dispatch_filter; \ No newline at end of file From f8ee6d04f417030b5ce489c6c3104a2e39fbfe29 Mon Sep 17 00:00:00 2001 From: Deepanshu Hooda Date: Thu, 14 Sep 2023 17:20:38 +0200 Subject: [PATCH 04/15] integration --- primitives/src/precompiles.rs | 45 ++++++++++++++++++++++++++++++ runtime/shibuya/src/lib.rs | 15 ++++++++++ runtime/shibuya/src/precompiles.rs | 7 +++-- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/primitives/src/precompiles.rs b/primitives/src/precompiles.rs index 2c80ff786..fe2ee4a80 100644 --- a/primitives/src/precompiles.rs +++ b/primitives/src/precompiles.rs @@ -18,7 +18,13 @@ #![cfg_attr(not(feature = "std"), no_std)] +use core::marker::PhantomData; + use fp_evm::{ExitError, PrecompileFailure}; +use frame_support::{ + dispatch::{DispatchClass, GetDispatchInfo, Pays}, + traits::InstanceFilter, +}; use pallet_evm_precompile_dispatch::DispatchValidateT; pub struct BlockAllDispatchValidate; @@ -36,3 +42,42 @@ impl DispatchValidateT }) } } + +pub struct DispatchFilterValidate + Default>( + PhantomData<(RuntimeCall, Filter)>, +); + +impl + Default> + DispatchValidateT for DispatchFilterValidate +{ + fn validate_before_dispatch( + _origin: &AccountId, + call: &RuntimeCall, + ) -> Option { + let info = call.get_dispatch_info(); + if !(info.pays_fee == Pays::Yes && info.class == DispatchClass::Normal) { + return Some(PrecompileFailure::Error { + exit_status: ExitError::Other("invalid call".into()), + }); + } else if Filter::default().filter(call) { + return None; + } else { + return Some(PrecompileFailure::Error { + exit_status: ExitError::Other("invalid call".into()), + }); + } + } +} + +mod test { + use super::*; + #[test] + fn all_non_whitelisted_call_should_fail() { + assert_eq!( + BlockAllDispatchValidate::validate_before_dispatch(&(), &()).unwrap(), + PrecompileFailure::Error { + exit_status: ExitError::Other("invalid call".into()), + } + ) + } +} diff --git a/runtime/shibuya/src/lib.rs b/runtime/shibuya/src/lib.rs index 24c352cc6..5f28a846b 100644 --- a/runtime/shibuya/src/lib.rs +++ b/runtime/shibuya/src/lib.rs @@ -1052,6 +1052,21 @@ impl pallet_sudo::Config for Runtime { type RuntimeCall = RuntimeCall; type WeightInfo = pallet_sudo::weights::SubstrateWeight; } +#[derive(Default)] +pub struct DispatchPrecompileFilter; + +impl InstanceFilter for DispatchPrecompileFilter { + fn filter(&self, c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Utility(pallet_utility::Call::batch { .. }) => true, + RuntimeCall::DappsStaking(_) => true, + _ => false, + } + } + fn is_superset(&self, _o: &Self) -> bool { + false + } +} parameter_types! { // One storage item; key size 32, value size 8. diff --git a/runtime/shibuya/src/precompiles.rs b/runtime/shibuya/src/precompiles.rs index b572c1997..d548acfb1 100644 --- a/runtime/shibuya/src/precompiles.rs +++ b/runtime/shibuya/src/precompiles.rs @@ -18,7 +18,8 @@ //! The Shibuya Network EVM precompiles. This can be compiled with ``#[no_std]`, ready for Wasm. -use astar_primitives::precompiles::BlockAllDispatchValidate; +use crate::{DispatchPrecompileFilter, RuntimeCall}; +use astar_primitives::precompiles::DispatchFilterValidate; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -78,7 +79,7 @@ where XcmPrecompile: Precompile, BatchPrecompile: Precompile, XvmPrecompile>: Precompile, - Dispatch: Precompile, + Dispatch>: Precompile, R: pallet_evm::Config + pallet_assets::Config + pallet_xcm::Config @@ -111,7 +112,7 @@ where a if a == hash(9) => Some(Blake2F::execute(handle)), // nor Ethereum precompiles : a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), - a if a == hash(1025) => Some(Dispatch::::execute(handle)), + a if a == hash(1025) => Some(Dispatch::>::execute(handle)), a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(1027) => Some(Ed25519Verify::execute(handle)), // Astar precompiles (starts from 0x5000): From c3c83831725db75d987be4b1cd195f636589d633 Mon Sep 17 00:00:00 2001 From: Deepanshu Hooda Date: Mon, 18 Sep 2023 12:44:32 +0200 Subject: [PATCH 05/15] more tests --- runtime/shibuya/src/lib.rs | 9 +++- runtime/shibuya/src/precompiles.rs | 5 +- tests/integration/src/dispatch_filter.rs | 65 ++++++++++++++++++++++-- tests/integration/src/lib.rs | 2 +- 4 files changed, 73 insertions(+), 8 deletions(-) diff --git a/runtime/shibuya/src/lib.rs b/runtime/shibuya/src/lib.rs index 5f28a846b..3a1a28ced 100644 --- a/runtime/shibuya/src/lib.rs +++ b/runtime/shibuya/src/lib.rs @@ -1058,7 +1058,14 @@ pub struct DispatchPrecompileFilter; impl InstanceFilter for DispatchPrecompileFilter { fn filter(&self, c: &RuntimeCall) -> bool { match c { - RuntimeCall::Utility(pallet_utility::Call::batch { .. }) => true, + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) => { + for call in calls { + if !DispatchPrecompileFilter::default().filter(call) { + return false; + } + } + true + } RuntimeCall::DappsStaking(_) => true, _ => false, } diff --git a/runtime/shibuya/src/precompiles.rs b/runtime/shibuya/src/precompiles.rs index d548acfb1..5c869a625 100644 --- a/runtime/shibuya/src/precompiles.rs +++ b/runtime/shibuya/src/precompiles.rs @@ -112,7 +112,10 @@ where a if a == hash(9) => Some(Blake2F::execute(handle)), // nor Ethereum precompiles : a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), - a if a == hash(1025) => Some(Dispatch::>::execute(handle)), + a if a == hash(1025) => Some(Dispatch::< + R, + DispatchFilterValidate, + >::execute(handle)), a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(1027) => Some(Ed25519Verify::execute(handle)), // Astar precompiles (starts from 0x5000): diff --git a/tests/integration/src/dispatch_filter.rs b/tests/integration/src/dispatch_filter.rs index 3da2deaca..193a3991c 100644 --- a/tests/integration/src/dispatch_filter.rs +++ b/tests/integration/src/dispatch_filter.rs @@ -21,15 +21,70 @@ use crate::setup::*; use frame_support::traits::InstanceFilter; #[test] -fn filter_accepts_batch_call_with_dappsstaking() { +fn filter_accepts_batch_call_with_dappsstaking_calls() { ExtBuilder::default().build().execute_with(|| { let contract = SmartContract::Evm(H160::repeat_byte(0x01)); - let inner_call = RuntimeCall::DappsStaking(DappStakingCall::Call::claim_staker{ - contract_id : contract.clone(), + let inner_call = RuntimeCall::DappsStaking(DappStakingCall::Call::claim_staker { + contract_id: contract.clone(), }); let call = RuntimeCall::Utility(UtilityCall::batch { - calls : vec![inner_call] + calls: vec![inner_call], }); assert!(DispatchPrecompileFilter.filter(&call)); }); -} \ No newline at end of file +} + +#[test] +fn filter_rejects_non_whitelisted_batch_calls() { + ExtBuilder::default().build().execute_with(|| { + // CASE1 - only non whitelisted calls + let transfer_call = RuntimeCall::Balances(BalancesCall::transfer { + dest: MultiAddress::Id(CAT), + value: 100_000_000_000, + }); + let transfer = Box::new(transfer_call); + let call = Box::new(RuntimeCall::Utility(UtilityCall::batch { + calls: vec![*transfer.clone()], + })); + + // Utility call containing Balances Call + assert!(!DispatchPrecompileFilter.filter(&call)); + + // CASE 2 - now whitelisted mixed with whitelisted calls + + let contract = SmartContract::Evm(H160::repeat_byte(0x01)); + let staking_call = RuntimeCall::DappsStaking(DappStakingCall::Call::claim_staker { + contract_id: contract.clone(), + }); + let staking = Box::new(staking_call); + + let call = Box::new(RuntimeCall::Utility(UtilityCall::batch { + calls: vec![*transfer, *staking.clone()], + })); + + // Utility call containing Balances Call and Dappsstaking Call Fails filter + assert!(!DispatchPrecompileFilter.filter(&call)); + }); +} + +#[test] +fn filter_accepts_dappsstaking_calls() { + ExtBuilder::default().build().execute_with(|| { + let contract = SmartContract::Evm(H160::repeat_byte(0x01)); + let stake_call = RuntimeCall::DappsStaking(DappStakingCall::Call::claim_staker { + contract_id: contract.clone(), + }); + assert!(DispatchPrecompileFilter.filter(&stake_call)); + }); +} + +#[test] +fn filter_rejects_non_whitelisted_calls() { + ExtBuilder::default().build().execute_with(|| { + let transfer_call = RuntimeCall::Balances(BalancesCall::transfer { + dest: MultiAddress::Id(CAT), + value: 100_000_000_000, + }); + assert!(!DispatchPrecompileFilter.filter(&transfer_call)); + }) +} diff --git a/tests/integration/src/lib.rs b/tests/integration/src/lib.rs index bbbdae52b..4779ed24a 100644 --- a/tests/integration/src/lib.rs +++ b/tests/integration/src/lib.rs @@ -33,4 +33,4 @@ mod assets; mod xvm; #[cfg(feature = "shibuya")] -mod dispatch_filter; \ No newline at end of file +mod dispatch_filter; From c04f80cba0f104792b4a2b3b7adc5daa2af5bf5f Mon Sep 17 00:00:00 2001 From: Deepanshu Hooda Date: Mon, 18 Sep 2023 12:57:00 +0200 Subject: [PATCH 06/15] fix test names --- tests/integration/src/dispatch_filter.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/integration/src/dispatch_filter.rs b/tests/integration/src/dispatch_filter.rs index 193a3991c..f3765a45d 100644 --- a/tests/integration/src/dispatch_filter.rs +++ b/tests/integration/src/dispatch_filter.rs @@ -20,8 +20,9 @@ use crate::setup::*; use frame_support::traits::InstanceFilter; +/// Whitelisted Calls are defined in the runtime #[test] -fn filter_accepts_batch_call_with_dappsstaking_calls() { +fn filter_accepts_batch_call_with_whitelisted_calls() { ExtBuilder::default().build().execute_with(|| { let contract = SmartContract::Evm(H160::repeat_byte(0x01)); let inner_call = RuntimeCall::DappsStaking(DappStakingCall::Call::claim_staker { @@ -68,7 +69,7 @@ fn filter_rejects_non_whitelisted_batch_calls() { } #[test] -fn filter_accepts_dappsstaking_calls() { +fn filter_accepts_whitelisted_calls() { ExtBuilder::default().build().execute_with(|| { let contract = SmartContract::Evm(H160::repeat_byte(0x01)); let stake_call = RuntimeCall::DappsStaking(DappStakingCall::Call::claim_staker { From a5dc1b1368e0f4d307c3bbf1dcc690839b021798 Mon Sep 17 00:00:00 2001 From: Deepanshu Hooda Date: Mon, 18 Sep 2023 18:35:13 +0200 Subject: [PATCH 07/15] clippy fix --- primitives/src/precompiles.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/primitives/src/precompiles.rs b/primitives/src/precompiles.rs index fe2ee4a80..54f588a92 100644 --- a/primitives/src/precompiles.rs +++ b/primitives/src/precompiles.rs @@ -69,6 +69,7 @@ impl Date: Tue, 19 Sep 2023 10:28:41 +0200 Subject: [PATCH 08/15] add filter to all runtimes --- runtime/astar/src/lib.rs | 23 +++++++++++++++++++++++ runtime/astar/src/precompiles.rs | 10 +++++++--- runtime/local/src/lib.rs | 23 +++++++++++++++++++++++ runtime/local/src/precompiles.rs | 10 +++++++--- runtime/shiden/src/lib.rs | 23 +++++++++++++++++++++++ runtime/shiden/src/precompiles.rs | 10 +++++++--- 6 files changed, 90 insertions(+), 9 deletions(-) diff --git a/runtime/astar/src/lib.rs b/runtime/astar/src/lib.rs index 816dbd280..b7c8038ac 100644 --- a/runtime/astar/src/lib.rs +++ b/runtime/astar/src/lib.rs @@ -844,6 +844,29 @@ impl pallet_xc_asset_config::Config for Runtime { type WeightInfo = pallet_xc_asset_config::weights::SubstrateWeight; } +#[derive(Default)] +pub struct DispatchPrecompileFilter; + +impl InstanceFilter for DispatchPrecompileFilter { + fn filter(&self, c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) => { + for call in calls { + if !DispatchPrecompileFilter::default().filter(call) { + return false; + } + } + true + } + RuntimeCall::DappsStaking(_) => true, + _ => false, + } + } + fn is_superset(&self, _o: &Self) -> bool { + false + } +} + /// The type used to represent the kinds of proxying allowed. #[derive( Copy, diff --git a/runtime/astar/src/precompiles.rs b/runtime/astar/src/precompiles.rs index 28d3b7b91..bbc8a489a 100644 --- a/runtime/astar/src/precompiles.rs +++ b/runtime/astar/src/precompiles.rs @@ -18,7 +18,8 @@ //! The Astar Network EVM precompiles. This can be compiled with ``#[no_std]`, ready for Wasm. -use astar_primitives::precompiles::BlockAllDispatchValidate; +use crate::{DispatchPrecompileFilter, RuntimeCall}; +use astar_primitives::precompiles::DispatchFilterValidate; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -75,7 +76,7 @@ where DappsStakingWrapper: Precompile, BatchPrecompile: Precompile, XcmPrecompile: Precompile, - Dispatch: Precompile, + Dispatch>: Precompile, R: pallet_evm::Config + pallet_assets::Config + pallet_xcm::Config @@ -107,7 +108,10 @@ where a if a == hash(9) => Some(Blake2F::execute(handle)), // nor Ethereum precompiles : a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), - a if a == hash(1025) => Some(Dispatch::::execute(handle)), + a if a == hash(1025) => Some(Dispatch::< + R, + DispatchFilterValidate, + >::execute(handle)), a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(1027) => Some(Ed25519Verify::execute(handle)), // Astar precompiles (starts from 0x5000): diff --git a/runtime/local/src/lib.rs b/runtime/local/src/lib.rs index 40c1e7e9a..de118941f 100644 --- a/runtime/local/src/lib.rs +++ b/runtime/local/src/lib.rs @@ -845,6 +845,29 @@ impl pallet_sudo::Config for Runtime { type WeightInfo = pallet_sudo::weights::SubstrateWeight; } +#[derive(Default)] +pub struct DispatchPrecompileFilter; + +impl InstanceFilter for DispatchPrecompileFilter { + fn filter(&self, c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) => { + for call in calls { + if !DispatchPrecompileFilter::default().filter(call) { + return false; + } + } + true + } + RuntimeCall::DappsStaking(_) => true, + _ => false, + } + } + fn is_superset(&self, _o: &Self) -> bool { + false + } +} + /// The type used to represent the kinds of proxying allowed. #[derive( Copy, diff --git a/runtime/local/src/precompiles.rs b/runtime/local/src/precompiles.rs index 180f3866d..d14eb5314 100644 --- a/runtime/local/src/precompiles.rs +++ b/runtime/local/src/precompiles.rs @@ -18,7 +18,8 @@ //! The Local EVM precompiles. This can be compiled with ``#[no_std]`, ready for Wasm. -use astar_primitives::precompiles::BlockAllDispatchValidate; +use crate::{DispatchPrecompileFilter, RuntimeCall}; +use astar_primitives::precompiles::DispatchFilterValidate; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -73,7 +74,7 @@ where DappsStakingWrapper: Precompile, BatchPrecompile: Precompile, XvmPrecompile>: Precompile, - Dispatch: Precompile, + Dispatch>: Precompile, R: pallet_evm::Config + pallet_xvm::Config + pallet_assets::Config @@ -104,7 +105,10 @@ where a if a == hash(9) => Some(Blake2F::execute(handle)), // nor Ethereum precompiles : a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), - a if a == hash(1025) => Some(Dispatch::::execute(handle)), + a if a == hash(1025) => Some(Dispatch::< + R, + DispatchFilterValidate, + >::execute(handle)), a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(1027) => Some(Ed25519Verify::execute(handle)), // Astar precompiles (starts from 0x5000): diff --git a/runtime/shiden/src/lib.rs b/runtime/shiden/src/lib.rs index f4bee2448..c1e971301 100644 --- a/runtime/shiden/src/lib.rs +++ b/runtime/shiden/src/lib.rs @@ -832,6 +832,29 @@ impl pallet_xc_asset_config::Config for Runtime { type WeightInfo = pallet_xc_asset_config::weights::SubstrateWeight; } +#[derive(Default)] +pub struct DispatchPrecompileFilter; + +impl InstanceFilter for DispatchPrecompileFilter { + fn filter(&self, c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) => { + for call in calls { + if !DispatchPrecompileFilter::default().filter(call) { + return false; + } + } + true + } + RuntimeCall::DappsStaking(_) => true, + _ => false, + } + } + fn is_superset(&self, _o: &Self) -> bool { + false + } +} + /// The type used to represent the kinds of proxying allowed. #[derive( Copy, diff --git a/runtime/shiden/src/precompiles.rs b/runtime/shiden/src/precompiles.rs index 5594b2494..f03bd02f3 100644 --- a/runtime/shiden/src/precompiles.rs +++ b/runtime/shiden/src/precompiles.rs @@ -18,7 +18,8 @@ //! The Shiden Network EVM precompiles. This can be compiled with ``#[no_std]`, ready for Wasm. -use astar_primitives::precompiles::BlockAllDispatchValidate; +use crate::{DispatchPrecompileFilter, RuntimeCall}; +use astar_primitives::precompiles::DispatchFilterValidate; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -75,7 +76,7 @@ where DappsStakingWrapper: Precompile, BatchPrecompile: Precompile, XcmPrecompile: Precompile, - Dispatch: Precompile, + Dispatch>: Precompile, R: pallet_evm::Config + pallet_assets::Config + pallet_xcm::Config @@ -107,7 +108,10 @@ where a if a == hash(9) => Some(Blake2F::execute(handle)), // nor Ethereum precompiles : a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), - a if a == hash(1025) => Some(Dispatch::::execute(handle)), + a if a == hash(1025) => Some(Dispatch::< + R, + DispatchFilterValidate, + >::execute(handle)), a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(1027) => Some(Ed25519Verify::execute(handle)), // Astar precompiles (starts from 0x5000): From e8dd394709424321cd739d7dbbc6fb6b351c57df Mon Sep 17 00:00:00 2001 From: Deepanshu Hooda Date: Wed, 20 Sep 2023 17:16:15 +0530 Subject: [PATCH 09/15] add comments and feature flags --- primitives/src/precompiles.rs | 3 +++ runtime/astar/src/lib.rs | 1 + runtime/local/src/lib.rs | 1 + runtime/shibuya/src/lib.rs | 2 ++ runtime/shiden/src/lib.rs | 1 + tests/integration/src/lib.rs | 2 +- 6 files changed, 9 insertions(+), 1 deletion(-) diff --git a/primitives/src/precompiles.rs b/primitives/src/precompiles.rs index 54f588a92..ac4cabb21 100644 --- a/primitives/src/precompiles.rs +++ b/primitives/src/precompiles.rs @@ -27,6 +27,7 @@ use frame_support::{ }; use pallet_evm_precompile_dispatch::DispatchValidateT; +/// Struct that blocks all runtime calls to Dispatch Precompile pub struct BlockAllDispatchValidate; /// The default implementation of `DispatchValidateT`. @@ -43,6 +44,8 @@ impl DispatchValidateT } } +/// Struct that allows only whitelisted runtime calls to pass through dispatch precompile, +/// Whitelisted calls are defined in runtime pub struct DispatchFilterValidate + Default>( PhantomData<(RuntimeCall, Filter)>, ); diff --git a/runtime/astar/src/lib.rs b/runtime/astar/src/lib.rs index b7c8038ac..05a0f59ab 100644 --- a/runtime/astar/src/lib.rs +++ b/runtime/astar/src/lib.rs @@ -844,6 +844,7 @@ impl pallet_xc_asset_config::Config for Runtime { type WeightInfo = pallet_xc_asset_config::weights::SubstrateWeight; } +/// Filter that only allows whitelisted runtime call to pass through dispatch precompile #[derive(Default)] pub struct DispatchPrecompileFilter; diff --git a/runtime/local/src/lib.rs b/runtime/local/src/lib.rs index de118941f..88bceef72 100644 --- a/runtime/local/src/lib.rs +++ b/runtime/local/src/lib.rs @@ -845,6 +845,7 @@ impl pallet_sudo::Config for Runtime { type WeightInfo = pallet_sudo::weights::SubstrateWeight; } +/// Filter that only allows whitelisted runtime call to pass through dispatch precompile #[derive(Default)] pub struct DispatchPrecompileFilter; diff --git a/runtime/shibuya/src/lib.rs b/runtime/shibuya/src/lib.rs index 3a1a28ced..deb3ca96f 100644 --- a/runtime/shibuya/src/lib.rs +++ b/runtime/shibuya/src/lib.rs @@ -1052,6 +1052,8 @@ impl pallet_sudo::Config for Runtime { type RuntimeCall = RuntimeCall; type WeightInfo = pallet_sudo::weights::SubstrateWeight; } + +/// Filter that only allows whitelisted runtime call to pass through dispatch precompile #[derive(Default)] pub struct DispatchPrecompileFilter; diff --git a/runtime/shiden/src/lib.rs b/runtime/shiden/src/lib.rs index c1e971301..4c479f948 100644 --- a/runtime/shiden/src/lib.rs +++ b/runtime/shiden/src/lib.rs @@ -832,6 +832,7 @@ impl pallet_xc_asset_config::Config for Runtime { type WeightInfo = pallet_xc_asset_config::weights::SubstrateWeight; } +/// Filter that only allows whitelisted runtime call to pass through dispatch precompile #[derive(Default)] pub struct DispatchPrecompileFilter; diff --git a/tests/integration/src/lib.rs b/tests/integration/src/lib.rs index 4779ed24a..d11445717 100644 --- a/tests/integration/src/lib.rs +++ b/tests/integration/src/lib.rs @@ -32,5 +32,5 @@ mod assets; #[cfg(feature = "shibuya")] mod xvm; -#[cfg(feature = "shibuya")] +#[cfg(any(feature = "shibuya", feature = "shiden", feature = "astar"))] mod dispatch_filter; From 74651c10cd2844617720d657a12c87c62481380a Mon Sep 17 00:00:00 2001 From: Deepanshu Hooda Date: Wed, 20 Sep 2023 19:40:44 +0530 Subject: [PATCH 10/15] add batch_all to whitelist call --- runtime/astar/src/lib.rs | 3 ++- runtime/local/src/lib.rs | 3 ++- runtime/shibuya/src/lib.rs | 3 ++- runtime/shiden/src/lib.rs | 3 ++- tests/integration/src/dispatch_filter.rs | 17 +++++++++++++++++ 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/runtime/astar/src/lib.rs b/runtime/astar/src/lib.rs index 05a0f59ab..4c0b0a1d4 100644 --- a/runtime/astar/src/lib.rs +++ b/runtime/astar/src/lib.rs @@ -851,7 +851,8 @@ pub struct DispatchPrecompileFilter; impl InstanceFilter for DispatchPrecompileFilter { fn filter(&self, c: &RuntimeCall) -> bool { match c { - RuntimeCall::Utility(pallet_utility::Call::batch { calls }) => { + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) + | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { for call in calls { if !DispatchPrecompileFilter::default().filter(call) { return false; diff --git a/runtime/local/src/lib.rs b/runtime/local/src/lib.rs index 88bceef72..39a7dd8c6 100644 --- a/runtime/local/src/lib.rs +++ b/runtime/local/src/lib.rs @@ -852,7 +852,8 @@ pub struct DispatchPrecompileFilter; impl InstanceFilter for DispatchPrecompileFilter { fn filter(&self, c: &RuntimeCall) -> bool { match c { - RuntimeCall::Utility(pallet_utility::Call::batch { calls }) => { + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) + | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { for call in calls { if !DispatchPrecompileFilter::default().filter(call) { return false; diff --git a/runtime/shibuya/src/lib.rs b/runtime/shibuya/src/lib.rs index deb3ca96f..d9f154cb5 100644 --- a/runtime/shibuya/src/lib.rs +++ b/runtime/shibuya/src/lib.rs @@ -1060,7 +1060,8 @@ pub struct DispatchPrecompileFilter; impl InstanceFilter for DispatchPrecompileFilter { fn filter(&self, c: &RuntimeCall) -> bool { match c { - RuntimeCall::Utility(pallet_utility::Call::batch { calls }) => { + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) + | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { for call in calls { if !DispatchPrecompileFilter::default().filter(call) { return false; diff --git a/runtime/shiden/src/lib.rs b/runtime/shiden/src/lib.rs index 4c479f948..12fa796b3 100644 --- a/runtime/shiden/src/lib.rs +++ b/runtime/shiden/src/lib.rs @@ -839,7 +839,8 @@ pub struct DispatchPrecompileFilter; impl InstanceFilter for DispatchPrecompileFilter { fn filter(&self, c: &RuntimeCall) -> bool { match c { - RuntimeCall::Utility(pallet_utility::Call::batch { calls }) => { + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) + | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { for call in calls { if !DispatchPrecompileFilter::default().filter(call) { return false; diff --git a/tests/integration/src/dispatch_filter.rs b/tests/integration/src/dispatch_filter.rs index f3765a45d..167da7b6a 100644 --- a/tests/integration/src/dispatch_filter.rs +++ b/tests/integration/src/dispatch_filter.rs @@ -89,3 +89,20 @@ fn filter_rejects_non_whitelisted_calls() { assert!(!DispatchPrecompileFilter.filter(&transfer_call)); }) } + +#[test] +fn filter_accepts_whitelisted_batch_all_calls() { + ExtBuilder::default().build().execute_with(|| { + let contract = SmartContract::Evm(H160::repeat_byte(0x01)); + let inner_call1 = RuntimeCall::DappsStaking(DappStakingCall::Call::claim_staker { + contract_id: contract.clone(), + }); + let inner_call2 = RuntimeCall::DappsStaking(DappStakingCall::Call::claim_staker { + contract_id: contract.clone(), + }); + let call = RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![inner_call1, inner_call2], + }); + assert!(DispatchPrecompileFilter.filter(&call)); + }); +} From 69b6fc06024a26b451e31ba5da501f653b835115 Mon Sep 17 00:00:00 2001 From: Deepanshu Hooda Date: Thu, 21 Sep 2023 18:16:30 +0530 Subject: [PATCH 11/15] remove BlockAll and refactor code --- primitives/src/precompiles.rs | 31 ------------------------------ runtime/astar/src/lib.rs | 26 +------------------------ runtime/astar/src/precompiles.rs | 27 +++++++++++++++++++++++++- runtime/local/src/lib.rs | 26 +------------------------ runtime/local/src/precompiles.rs | 28 ++++++++++++++++++++++++++- runtime/shibuya/src/lib.rs | 27 ++------------------------ runtime/shibuya/src/precompiles.rs | 28 ++++++++++++++++++++++++++- runtime/shiden/src/lib.rs | 26 +------------------------ runtime/shiden/src/precompiles.rs | 28 ++++++++++++++++++++++++++- 9 files changed, 112 insertions(+), 135 deletions(-) diff --git a/primitives/src/precompiles.rs b/primitives/src/precompiles.rs index ac4cabb21..7696c7d35 100644 --- a/primitives/src/precompiles.rs +++ b/primitives/src/precompiles.rs @@ -27,23 +27,6 @@ use frame_support::{ }; use pallet_evm_precompile_dispatch::DispatchValidateT; -/// Struct that blocks all runtime calls to Dispatch Precompile -pub struct BlockAllDispatchValidate; - -/// The default implementation of `DispatchValidateT`. -impl DispatchValidateT - for BlockAllDispatchValidate -{ - fn validate_before_dispatch( - _origin: &AccountId, - _call: &RuntimeCall, - ) -> Option { - Some(PrecompileFailure::Error { - exit_status: ExitError::Other("invalid call".into()), - }) - } -} - /// Struct that allows only whitelisted runtime calls to pass through dispatch precompile, /// Whitelisted calls are defined in runtime pub struct DispatchFilterValidate + Default>( @@ -71,17 +54,3 @@ impl; } -/// Filter that only allows whitelisted runtime call to pass through dispatch precompile -#[derive(Default)] -pub struct DispatchPrecompileFilter; - -impl InstanceFilter for DispatchPrecompileFilter { - fn filter(&self, c: &RuntimeCall) -> bool { - match c { - RuntimeCall::Utility(pallet_utility::Call::batch { calls }) - | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { - for call in calls { - if !DispatchPrecompileFilter::default().filter(call) { - return false; - } - } - true - } - RuntimeCall::DappsStaking(_) => true, - _ => false, - } - } - fn is_superset(&self, _o: &Self) -> bool { - false - } -} - /// The type used to represent the kinds of proxying allowed. #[derive( Copy, diff --git a/runtime/astar/src/precompiles.rs b/runtime/astar/src/precompiles.rs index bbc8a489a..460544177 100644 --- a/runtime/astar/src/precompiles.rs +++ b/runtime/astar/src/precompiles.rs @@ -18,8 +18,9 @@ //! The Astar Network EVM precompiles. This can be compiled with ``#[no_std]`, ready for Wasm. -use crate::{DispatchPrecompileFilter, RuntimeCall}; +use crate::RuntimeCall; use astar_primitives::precompiles::DispatchFilterValidate; +use frame_support::traits::InstanceFilter; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -47,6 +48,30 @@ use xcm::latest::prelude::MultiLocation; /// to Erc20AssetsPrecompileSet pub const ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4]; +/// Filter that only allows whitelisted runtime call to pass through dispatch precompile +#[derive(Default)] +pub struct DispatchPrecompileFilter; + +impl InstanceFilter for DispatchPrecompileFilter { + fn filter(&self, c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) + | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { + for call in calls { + if !DispatchPrecompileFilter::default().filter(call) { + return false; + } + } + true + } + RuntimeCall::DappsStaking(_) => true, + _ => false, + } + } + fn is_superset(&self, _o: &Self) -> bool { + false + } +} /// The PrecompileSet installed in the Astar runtime. #[derive(Debug, Default, Clone, Copy)] pub struct AstarNetworkPrecompiles(PhantomData<(R, C)>); diff --git a/runtime/local/src/lib.rs b/runtime/local/src/lib.rs index 39a7dd8c6..007495f29 100644 --- a/runtime/local/src/lib.rs +++ b/runtime/local/src/lib.rs @@ -65,6 +65,7 @@ pub use astar_primitives::{ Index, Signature, }; +pub use crate::precompiles::DispatchPrecompileFilter; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; @@ -845,31 +846,6 @@ impl pallet_sudo::Config for Runtime { type WeightInfo = pallet_sudo::weights::SubstrateWeight; } -/// Filter that only allows whitelisted runtime call to pass through dispatch precompile -#[derive(Default)] -pub struct DispatchPrecompileFilter; - -impl InstanceFilter for DispatchPrecompileFilter { - fn filter(&self, c: &RuntimeCall) -> bool { - match c { - RuntimeCall::Utility(pallet_utility::Call::batch { calls }) - | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { - for call in calls { - if !DispatchPrecompileFilter::default().filter(call) { - return false; - } - } - true - } - RuntimeCall::DappsStaking(_) => true, - _ => false, - } - } - fn is_superset(&self, _o: &Self) -> bool { - false - } -} - /// The type used to represent the kinds of proxying allowed. #[derive( Copy, diff --git a/runtime/local/src/precompiles.rs b/runtime/local/src/precompiles.rs index d14eb5314..d0c56ab85 100644 --- a/runtime/local/src/precompiles.rs +++ b/runtime/local/src/precompiles.rs @@ -18,8 +18,9 @@ //! The Local EVM precompiles. This can be compiled with ``#[no_std]`, ready for Wasm. -use crate::{DispatchPrecompileFilter, RuntimeCall}; +use crate::RuntimeCall; use astar_primitives::precompiles::DispatchFilterValidate; +use frame_support::traits::InstanceFilter; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -45,6 +46,31 @@ use sp_std::marker::PhantomData; /// to Erc20AssetsPrecompileSet pub const ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4]; +/// Filter that only allows whitelisted runtime call to pass through dispatch precompile +#[derive(Default)] +pub struct DispatchPrecompileFilter; + +impl InstanceFilter for DispatchPrecompileFilter { + fn filter(&self, c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) + | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { + for call in calls { + if !DispatchPrecompileFilter::default().filter(call) { + return false; + } + } + true + } + RuntimeCall::DappsStaking(_) => true, + _ => false, + } + } + fn is_superset(&self, _o: &Self) -> bool { + false + } +} + /// The PrecompileSet installed in the Local runtime. #[derive(Debug, Default, Clone, Copy)] pub struct LocalNetworkPrecompiles(PhantomData); diff --git a/runtime/shibuya/src/lib.rs b/runtime/shibuya/src/lib.rs index d9f154cb5..8eb673221 100644 --- a/runtime/shibuya/src/lib.rs +++ b/runtime/shibuya/src/lib.rs @@ -74,6 +74,8 @@ pub use astar_primitives::{ Index, Signature, }; +pub use crate::precompiles::DispatchPrecompileFilter; + use pallet_evm_precompile_assets_erc20::AddressToAssetId; #[cfg(any(feature = "std", test))] @@ -1053,31 +1055,6 @@ impl pallet_sudo::Config for Runtime { type WeightInfo = pallet_sudo::weights::SubstrateWeight; } -/// Filter that only allows whitelisted runtime call to pass through dispatch precompile -#[derive(Default)] -pub struct DispatchPrecompileFilter; - -impl InstanceFilter for DispatchPrecompileFilter { - fn filter(&self, c: &RuntimeCall) -> bool { - match c { - RuntimeCall::Utility(pallet_utility::Call::batch { calls }) - | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { - for call in calls { - if !DispatchPrecompileFilter::default().filter(call) { - return false; - } - } - true - } - RuntimeCall::DappsStaking(_) => true, - _ => false, - } - } - fn is_superset(&self, _o: &Self) -> bool { - false - } -} - parameter_types! { // One storage item; key size 32, value size 8. pub const ProxyDepositBase: Balance = deposit(1, 8); diff --git a/runtime/shibuya/src/precompiles.rs b/runtime/shibuya/src/precompiles.rs index 5c869a625..7c0ed550d 100644 --- a/runtime/shibuya/src/precompiles.rs +++ b/runtime/shibuya/src/precompiles.rs @@ -18,8 +18,9 @@ //! The Shibuya Network EVM precompiles. This can be compiled with ``#[no_std]`, ready for Wasm. -use crate::{DispatchPrecompileFilter, RuntimeCall}; +use crate::RuntimeCall; use astar_primitives::precompiles::DispatchFilterValidate; +use frame_support::traits::InstanceFilter; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -48,6 +49,31 @@ use xcm::latest::prelude::MultiLocation; /// to Erc20AssetsPrecompileSet pub const ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4]; +/// Filter that only allows whitelisted runtime call to pass through dispatch precompile +#[derive(Default)] +pub struct DispatchPrecompileFilter; + +impl InstanceFilter for DispatchPrecompileFilter { + fn filter(&self, c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) + | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { + for call in calls { + if !DispatchPrecompileFilter::default().filter(call) { + return false; + } + } + true + } + RuntimeCall::DappsStaking(_) => true, + _ => false, + } + } + fn is_superset(&self, _o: &Self) -> bool { + false + } +} + /// The PrecompileSet installed in the Shiden runtime. #[derive(Debug, Default, Clone, Copy)] pub struct ShibuyaNetworkPrecompiles(PhantomData<(R, C)>); diff --git a/runtime/shiden/src/lib.rs b/runtime/shiden/src/lib.rs index 12fa796b3..4d93b3b0f 100644 --- a/runtime/shiden/src/lib.rs +++ b/runtime/shiden/src/lib.rs @@ -67,6 +67,7 @@ use sp_runtime::{ }; use sp_std::prelude::*; +pub use crate::precompiles::DispatchPrecompileFilter; pub use astar_primitives::{ evm::EvmRevertCodeHandler, xcm::AssetLocationIdConverter, AccountId, Address, AssetId, Balance, BlockNumber, Hash, Header, Index, Signature, @@ -832,31 +833,6 @@ impl pallet_xc_asset_config::Config for Runtime { type WeightInfo = pallet_xc_asset_config::weights::SubstrateWeight; } -/// Filter that only allows whitelisted runtime call to pass through dispatch precompile -#[derive(Default)] -pub struct DispatchPrecompileFilter; - -impl InstanceFilter for DispatchPrecompileFilter { - fn filter(&self, c: &RuntimeCall) -> bool { - match c { - RuntimeCall::Utility(pallet_utility::Call::batch { calls }) - | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { - for call in calls { - if !DispatchPrecompileFilter::default().filter(call) { - return false; - } - } - true - } - RuntimeCall::DappsStaking(_) => true, - _ => false, - } - } - fn is_superset(&self, _o: &Self) -> bool { - false - } -} - /// The type used to represent the kinds of proxying allowed. #[derive( Copy, diff --git a/runtime/shiden/src/precompiles.rs b/runtime/shiden/src/precompiles.rs index f03bd02f3..9c242bd9d 100644 --- a/runtime/shiden/src/precompiles.rs +++ b/runtime/shiden/src/precompiles.rs @@ -18,8 +18,9 @@ //! The Shiden Network EVM precompiles. This can be compiled with ``#[no_std]`, ready for Wasm. -use crate::{DispatchPrecompileFilter, RuntimeCall}; +use crate::RuntimeCall; use astar_primitives::precompiles::DispatchFilterValidate; +use frame_support::traits::InstanceFilter; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -47,6 +48,31 @@ use xcm::latest::prelude::MultiLocation; /// to Erc20AssetsPrecompileSet pub const ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4]; +/// Filter that only allows whitelisted runtime call to pass through dispatch precompile +#[derive(Default)] +pub struct DispatchPrecompileFilter; + +impl InstanceFilter for DispatchPrecompileFilter { + fn filter(&self, c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) + | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { + for call in calls { + if !DispatchPrecompileFilter::default().filter(call) { + return false; + } + } + true + } + RuntimeCall::DappsStaking(_) => true, + _ => false, + } + } + fn is_superset(&self, _o: &Self) -> bool { + false + } +} + /// The PrecompileSet installed in the Shiden runtime. #[derive(Debug, Default, Clone, Copy)] pub struct ShidenNetworkPrecompiles(PhantomData<(R, C)>); From 23c8a46cc75a8fc07bef26831bd0f63e13c195dd Mon Sep 17 00:00:00 2001 From: Deepanshu Hooda Date: Fri, 22 Sep 2023 17:23:50 +0530 Subject: [PATCH 12/15] use Contains instead of InstanceFilter --- primitives/src/precompiles.rs | 20 +++++++------- runtime/astar/src/lib.rs | 2 +- runtime/astar/src/precompiles.rs | 26 +++++++------------ runtime/local/src/lib.rs | 2 +- runtime/local/src/precompiles.rs | 25 ++++++------------ runtime/shibuya/src/lib.rs | 2 +- runtime/shibuya/src/precompiles.rs | 25 ++++++------------ runtime/shiden/src/lib.rs | 2 +- runtime/shiden/src/precompiles.rs | 25 ++++++------------ ...ilter.rs => dispatch_precompile_filter.rs} | 14 +++++----- tests/integration/src/lib.rs | 2 +- 11 files changed, 56 insertions(+), 89 deletions(-) rename tests/integration/src/{dispatch_filter.rs => dispatch_precompile_filter.rs} (89%) diff --git a/primitives/src/precompiles.rs b/primitives/src/precompiles.rs index 7696c7d35..165a9f0da 100644 --- a/primitives/src/precompiles.rs +++ b/primitives/src/precompiles.rs @@ -23,17 +23,17 @@ use core::marker::PhantomData; use fp_evm::{ExitError, PrecompileFailure}; use frame_support::{ dispatch::{DispatchClass, GetDispatchInfo, Pays}, - traits::InstanceFilter, + traits::Contains, }; use pallet_evm_precompile_dispatch::DispatchValidateT; /// Struct that allows only whitelisted runtime calls to pass through dispatch precompile, /// Whitelisted calls are defined in runtime -pub struct DispatchFilterValidate + Default>( +pub struct DispatchFilterValidate>( PhantomData<(RuntimeCall, Filter)>, ); -impl + Default> +impl> DispatchValidateT for DispatchFilterValidate { fn validate_before_dispatch( @@ -41,16 +41,18 @@ impl Option { let info = call.get_dispatch_info(); - if !(info.pays_fee == Pays::Yes && info.class == DispatchClass::Normal) { + let paid_normal_call = info.pays_fee == Pays::Yes && info.class == DispatchClass::Normal; + if !paid_normal_call { return Some(PrecompileFailure::Error { exit_status: ExitError::Other("invalid call".into()), }); - } else if Filter::default().filter(call) { - return None; + } + if Filter::contains(call) { + None } else { - return Some(PrecompileFailure::Error { - exit_status: ExitError::Other("invalid call".into()), - }); + Some(PrecompileFailure::Error { + exit_status: ExitError::Other("call filtered out".into()), + }) } } } diff --git a/runtime/astar/src/lib.rs b/runtime/astar/src/lib.rs index e08c22d91..73fede90b 100644 --- a/runtime/astar/src/lib.rs +++ b/runtime/astar/src/lib.rs @@ -22,7 +22,7 @@ // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. #![recursion_limit = "256"] -pub use crate::precompiles::DispatchPrecompileFilter; +pub use crate::precompiles::WhitelistedCalls; pub use astar_primitives::{ evm::EvmRevertCodeHandler, xcm::AssetLocationIdConverter, AccountId, Address, AssetId, Balance, BlockNumber, Hash, Header, Index, Signature, diff --git a/runtime/astar/src/precompiles.rs b/runtime/astar/src/precompiles.rs index 460544177..3845c68fd 100644 --- a/runtime/astar/src/precompiles.rs +++ b/runtime/astar/src/precompiles.rs @@ -20,7 +20,7 @@ use crate::RuntimeCall; use astar_primitives::precompiles::DispatchFilterValidate; -use frame_support::traits::InstanceFilter; +use frame_support::traits::Contains; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -49,28 +49,20 @@ use xcm::latest::prelude::MultiLocation; pub const ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4]; /// Filter that only allows whitelisted runtime call to pass through dispatch precompile -#[derive(Default)] -pub struct DispatchPrecompileFilter; -impl InstanceFilter for DispatchPrecompileFilter { - fn filter(&self, c: &RuntimeCall) -> bool { - match c { +pub struct WhitelistedCalls; + +impl Contains for WhitelistedCalls { + fn contains(t: &RuntimeCall) -> bool { + match t { RuntimeCall::Utility(pallet_utility::Call::batch { calls }) | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { - for call in calls { - if !DispatchPrecompileFilter::default().filter(call) { - return false; - } - } - true + calls.iter().all(|call| WhitelistedCalls::contains(call)) } RuntimeCall::DappsStaking(_) => true, _ => false, } } - fn is_superset(&self, _o: &Self) -> bool { - false - } } /// The PrecompileSet installed in the Astar runtime. #[derive(Debug, Default, Clone, Copy)] @@ -101,7 +93,7 @@ where DappsStakingWrapper: Precompile, BatchPrecompile: Precompile, XcmPrecompile: Precompile, - Dispatch>: Precompile, + Dispatch>: Precompile, R: pallet_evm::Config + pallet_assets::Config + pallet_xcm::Config @@ -135,7 +127,7 @@ where a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), a if a == hash(1025) => Some(Dispatch::< R, - DispatchFilterValidate, + DispatchFilterValidate, >::execute(handle)), a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(1027) => Some(Ed25519Verify::execute(handle)), diff --git a/runtime/local/src/lib.rs b/runtime/local/src/lib.rs index 007495f29..b56409ecb 100644 --- a/runtime/local/src/lib.rs +++ b/runtime/local/src/lib.rs @@ -65,7 +65,7 @@ pub use astar_primitives::{ Index, Signature, }; -pub use crate::precompiles::DispatchPrecompileFilter; +pub use crate::precompiles::WhitelistedCalls; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; diff --git a/runtime/local/src/precompiles.rs b/runtime/local/src/precompiles.rs index d0c56ab85..6bf29d17f 100644 --- a/runtime/local/src/precompiles.rs +++ b/runtime/local/src/precompiles.rs @@ -20,7 +20,7 @@ use crate::RuntimeCall; use astar_primitives::precompiles::DispatchFilterValidate; -use frame_support::traits::InstanceFilter; +use frame_support::traits::Contains; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -47,28 +47,19 @@ use sp_std::marker::PhantomData; pub const ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4]; /// Filter that only allows whitelisted runtime call to pass through dispatch precompile -#[derive(Default)] -pub struct DispatchPrecompileFilter; +pub struct WhitelistedCalls; -impl InstanceFilter for DispatchPrecompileFilter { - fn filter(&self, c: &RuntimeCall) -> bool { - match c { +impl Contains for WhitelistedCalls { + fn contains(t: &RuntimeCall) -> bool { + match t { RuntimeCall::Utility(pallet_utility::Call::batch { calls }) | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { - for call in calls { - if !DispatchPrecompileFilter::default().filter(call) { - return false; - } - } - true + calls.iter().all(|call| WhitelistedCalls::contains(call)) } RuntimeCall::DappsStaking(_) => true, _ => false, } } - fn is_superset(&self, _o: &Self) -> bool { - false - } } /// The PrecompileSet installed in the Local runtime. @@ -100,7 +91,7 @@ where DappsStakingWrapper: Precompile, BatchPrecompile: Precompile, XvmPrecompile>: Precompile, - Dispatch>: Precompile, + Dispatch>: Precompile, R: pallet_evm::Config + pallet_xvm::Config + pallet_assets::Config @@ -133,7 +124,7 @@ where a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), a if a == hash(1025) => Some(Dispatch::< R, - DispatchFilterValidate, + DispatchFilterValidate, >::execute(handle)), a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(1027) => Some(Ed25519Verify::execute(handle)), diff --git a/runtime/shibuya/src/lib.rs b/runtime/shibuya/src/lib.rs index 8eb673221..ad27d222d 100644 --- a/runtime/shibuya/src/lib.rs +++ b/runtime/shibuya/src/lib.rs @@ -74,7 +74,7 @@ pub use astar_primitives::{ Index, Signature, }; -pub use crate::precompiles::DispatchPrecompileFilter; +pub use crate::precompiles::WhitelistedCalls; use pallet_evm_precompile_assets_erc20::AddressToAssetId; diff --git a/runtime/shibuya/src/precompiles.rs b/runtime/shibuya/src/precompiles.rs index 7c0ed550d..0965bcd57 100644 --- a/runtime/shibuya/src/precompiles.rs +++ b/runtime/shibuya/src/precompiles.rs @@ -20,7 +20,7 @@ use crate::RuntimeCall; use astar_primitives::precompiles::DispatchFilterValidate; -use frame_support::traits::InstanceFilter; +use frame_support::traits::Contains; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -50,28 +50,19 @@ use xcm::latest::prelude::MultiLocation; pub const ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4]; /// Filter that only allows whitelisted runtime call to pass through dispatch precompile -#[derive(Default)] -pub struct DispatchPrecompileFilter; +pub struct WhitelistedCalls; -impl InstanceFilter for DispatchPrecompileFilter { - fn filter(&self, c: &RuntimeCall) -> bool { - match c { +impl Contains for WhitelistedCalls { + fn contains(t: &RuntimeCall) -> bool { + match t { RuntimeCall::Utility(pallet_utility::Call::batch { calls }) | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { - for call in calls { - if !DispatchPrecompileFilter::default().filter(call) { - return false; - } - } - true + calls.iter().all(|call| WhitelistedCalls::contains(call)) } RuntimeCall::DappsStaking(_) => true, _ => false, } } - fn is_superset(&self, _o: &Self) -> bool { - false - } } /// The PrecompileSet installed in the Shiden runtime. @@ -105,7 +96,7 @@ where XcmPrecompile: Precompile, BatchPrecompile: Precompile, XvmPrecompile>: Precompile, - Dispatch>: Precompile, + Dispatch>: Precompile, R: pallet_evm::Config + pallet_assets::Config + pallet_xcm::Config @@ -140,7 +131,7 @@ where a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), a if a == hash(1025) => Some(Dispatch::< R, - DispatchFilterValidate, + DispatchFilterValidate, >::execute(handle)), a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(1027) => Some(Ed25519Verify::execute(handle)), diff --git a/runtime/shiden/src/lib.rs b/runtime/shiden/src/lib.rs index 4d93b3b0f..e0fc68804 100644 --- a/runtime/shiden/src/lib.rs +++ b/runtime/shiden/src/lib.rs @@ -67,7 +67,7 @@ use sp_runtime::{ }; use sp_std::prelude::*; -pub use crate::precompiles::DispatchPrecompileFilter; +pub use crate::precompiles::WhitelistedCalls; pub use astar_primitives::{ evm::EvmRevertCodeHandler, xcm::AssetLocationIdConverter, AccountId, Address, AssetId, Balance, BlockNumber, Hash, Header, Index, Signature, diff --git a/runtime/shiden/src/precompiles.rs b/runtime/shiden/src/precompiles.rs index 9c242bd9d..7dde89084 100644 --- a/runtime/shiden/src/precompiles.rs +++ b/runtime/shiden/src/precompiles.rs @@ -20,7 +20,7 @@ use crate::RuntimeCall; use astar_primitives::precompiles::DispatchFilterValidate; -use frame_support::traits::InstanceFilter; +use frame_support::traits::Contains; use pallet_evm::{ ExitRevert, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, PrecompileResult, PrecompileSet, @@ -49,28 +49,19 @@ use xcm::latest::prelude::MultiLocation; pub const ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4]; /// Filter that only allows whitelisted runtime call to pass through dispatch precompile -#[derive(Default)] -pub struct DispatchPrecompileFilter; +pub struct WhitelistedCalls; -impl InstanceFilter for DispatchPrecompileFilter { - fn filter(&self, c: &RuntimeCall) -> bool { - match c { +impl Contains for WhitelistedCalls { + fn contains(t: &RuntimeCall) -> bool { + match t { RuntimeCall::Utility(pallet_utility::Call::batch { calls }) | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { - for call in calls { - if !DispatchPrecompileFilter::default().filter(call) { - return false; - } - } - true + calls.iter().all(|call| WhitelistedCalls::contains(call)) } RuntimeCall::DappsStaking(_) => true, _ => false, } } - fn is_superset(&self, _o: &Self) -> bool { - false - } } /// The PrecompileSet installed in the Shiden runtime. @@ -102,7 +93,7 @@ where DappsStakingWrapper: Precompile, BatchPrecompile: Precompile, XcmPrecompile: Precompile, - Dispatch>: Precompile, + Dispatch>: Precompile, R: pallet_evm::Config + pallet_assets::Config + pallet_xcm::Config @@ -136,7 +127,7 @@ where a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), a if a == hash(1025) => Some(Dispatch::< R, - DispatchFilterValidate, + DispatchFilterValidate, >::execute(handle)), a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)), a if a == hash(1027) => Some(Ed25519Verify::execute(handle)), diff --git a/tests/integration/src/dispatch_filter.rs b/tests/integration/src/dispatch_precompile_filter.rs similarity index 89% rename from tests/integration/src/dispatch_filter.rs rename to tests/integration/src/dispatch_precompile_filter.rs index 167da7b6a..6dc5e1ed2 100644 --- a/tests/integration/src/dispatch_filter.rs +++ b/tests/integration/src/dispatch_precompile_filter.rs @@ -18,7 +18,7 @@ #![cfg(test)] use crate::setup::*; -use frame_support::traits::InstanceFilter; +use frame_support::traits::Contains; /// Whitelisted Calls are defined in the runtime #[test] @@ -31,7 +31,7 @@ fn filter_accepts_batch_call_with_whitelisted_calls() { let call = RuntimeCall::Utility(UtilityCall::batch { calls: vec![inner_call], }); - assert!(DispatchPrecompileFilter.filter(&call)); + assert!(WhitelistedCalls::contains(&call)); }); } @@ -49,7 +49,7 @@ fn filter_rejects_non_whitelisted_batch_calls() { })); // Utility call containing Balances Call - assert!(!DispatchPrecompileFilter.filter(&call)); + assert!(!WhitelistedCalls::contains(&call)); // CASE 2 - now whitelisted mixed with whitelisted calls @@ -64,7 +64,7 @@ fn filter_rejects_non_whitelisted_batch_calls() { })); // Utility call containing Balances Call and Dappsstaking Call Fails filter - assert!(!DispatchPrecompileFilter.filter(&call)); + assert!(!WhitelistedCalls::contains(&call)); }); } @@ -75,7 +75,7 @@ fn filter_accepts_whitelisted_calls() { let stake_call = RuntimeCall::DappsStaking(DappStakingCall::Call::claim_staker { contract_id: contract.clone(), }); - assert!(DispatchPrecompileFilter.filter(&stake_call)); + assert!(WhitelistedCalls::contains(&stake_call)); }); } @@ -86,7 +86,7 @@ fn filter_rejects_non_whitelisted_calls() { dest: MultiAddress::Id(CAT), value: 100_000_000_000, }); - assert!(!DispatchPrecompileFilter.filter(&transfer_call)); + assert!(!WhitelistedCalls::contains(&transfer_call)); }) } @@ -103,6 +103,6 @@ fn filter_accepts_whitelisted_batch_all_calls() { let call = RuntimeCall::Utility(UtilityCall::batch_all { calls: vec![inner_call1, inner_call2], }); - assert!(DispatchPrecompileFilter.filter(&call)); + assert!(WhitelistedCalls::contains(&call)); }); } diff --git a/tests/integration/src/lib.rs b/tests/integration/src/lib.rs index d11445717..087aa2f05 100644 --- a/tests/integration/src/lib.rs +++ b/tests/integration/src/lib.rs @@ -33,4 +33,4 @@ mod assets; mod xvm; #[cfg(any(feature = "shibuya", feature = "shiden", feature = "astar"))] -mod dispatch_filter; +mod dispatch_precompile_filter; From 6ca2376b9efb190db893a27cc548c168a6b4c80e Mon Sep 17 00:00:00 2001 From: Deepanshu Hooda Date: Mon, 25 Sep 2023 13:07:37 +0530 Subject: [PATCH 13/15] Add DispatchInfo tests --- Cargo.lock | 1 + primitives/src/precompiles.rs | 3 +- tests/integration/Cargo.toml | 1 + .../src/dispatch_precompile_filter.rs | 95 ++++++++++++++++++- 4 files changed, 97 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4fc78e125..fa62199e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4479,6 +4479,7 @@ dependencies = [ "pallet-ethereum-checked", "pallet-evm", "pallet-evm-precompile-assets-erc20", + "pallet-evm-precompile-dispatch", "pallet-proxy", "pallet-utility", "parity-scale-codec", diff --git a/primitives/src/precompiles.rs b/primitives/src/precompiles.rs index 165a9f0da..26e5abef5 100644 --- a/primitives/src/precompiles.rs +++ b/primitives/src/precompiles.rs @@ -27,8 +27,7 @@ use frame_support::{ }; use pallet_evm_precompile_dispatch::DispatchValidateT; -/// Struct that allows only whitelisted runtime calls to pass through dispatch precompile, -/// Whitelisted calls are defined in runtime +/// Struct that allows only calls based on `Filter` to pass through. pub struct DispatchFilterValidate>( PhantomData<(RuntimeCall, Filter)>, ); diff --git a/tests/integration/Cargo.toml b/tests/integration/Cargo.toml index bacba8f98..eb2ac7968 100644 --- a/tests/integration/Cargo.toml +++ b/tests/integration/Cargo.toml @@ -34,6 +34,7 @@ sp-runtime = { workspace = true } # astar dependencies pallet-ethereum-checked = { workspace = true } pallet-evm-precompile-assets-erc20 = { workspace = true } +pallet-evm-precompile-dispatch = { workspace = true } precompile-utils = { workspace = true } astar-primitives = { workspace = true } diff --git a/tests/integration/src/dispatch_precompile_filter.rs b/tests/integration/src/dispatch_precompile_filter.rs index 6dc5e1ed2..61a42f6a4 100644 --- a/tests/integration/src/dispatch_precompile_filter.rs +++ b/tests/integration/src/dispatch_precompile_filter.rs @@ -18,7 +18,13 @@ #![cfg(test)] use crate::setup::*; -use frame_support::traits::Contains; +use astar_primitives::precompiles::DispatchFilterValidate; +use fp_evm::{ExitError, PrecompileFailure}; +use frame_support::{ + dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, Pays}, + traits::Contains, +}; +use pallet_evm_precompile_dispatch::DispatchValidateT; /// Whitelisted Calls are defined in the runtime #[test] @@ -106,3 +112,90 @@ fn filter_accepts_whitelisted_batch_all_calls() { assert!(WhitelistedCalls::contains(&call)); }); } + +#[test] +fn test_correct_dispatch_info_works() { + ExtBuilder::default().build().execute_with(|| { + // Mock implementation + struct Filter; + struct AccountId; + enum RuntimeCall { + System, + DappsStaking, + } + impl GetDispatchInfo for RuntimeCall { + fn get_dispatch_info(&self) -> DispatchInfo { + // Default is Pays::Yes and DispatchCall::Normal + DispatchInfo::default() + } + } + impl Contains for Filter { + fn contains(t: &RuntimeCall) -> bool { + match t { + RuntimeCall::DappsStaking => true, + _ => false, + } + } + } + // Case 1: Whitelisted Call with correct Dispatch info + assert_eq!( + DispatchFilterValidate::::validate_before_dispatch( + &AccountId, + &RuntimeCall::DappsStaking + ), + Option::None + ); + // Case 2: Non-Whitelisted Call with correct Dispatch Info + assert_eq!( + DispatchFilterValidate::::validate_before_dispatch( + &AccountId, + &RuntimeCall::System + ), + Option::Some(PrecompileFailure::Error { + exit_status: ExitError::Other("call filtered out".into()), + }) + ); + }); +} + +#[test] +fn test_incorrect_dispatch_info_fails() { + ExtBuilder::default().build().execute_with(|| { + // Mock implementation + struct Filter; + struct AccountId; + enum RuntimeCall { + System, + DappsStaking, + } + impl GetDispatchInfo for RuntimeCall { + fn get_dispatch_info(&self) -> DispatchInfo { + DispatchInfo { + weight: Weight::default(), + class: DispatchClass::Normal, + // Should have been Pays::Yes for call to pass + pays_fee: Pays::No, + } + } + } + impl Contains for Filter { + fn contains(t: &RuntimeCall) -> bool { + match t { + RuntimeCall::DappsStaking => true, + _ => false, + } + } + } + + // WhiteListed Call fails because of incorrect DispatchInfo + assert_eq!( + DispatchFilterValidate::::validate_before_dispatch( + &AccountId, + &RuntimeCall::DappsStaking + ), + Option::Some(PrecompileFailure::Error { + exit_status: ExitError::Other("invalid call".into()), + }) + ); + }) +} From ccbeaad4b4d0cee7321c4940cf709bf81ddf5207 Mon Sep 17 00:00:00 2001 From: Deepanshu Hooda Date: Tue, 26 Sep 2023 21:36:57 +0530 Subject: [PATCH 14/15] add transfer fn of pallet assets to whitelist --- runtime/astar/src/precompiles.rs | 1 + runtime/local/src/precompiles.rs | 1 + runtime/shibuya/src/precompiles.rs | 1 + runtime/shiden/src/precompiles.rs | 1 + .../src/dispatch_precompile_filter.rs | 24 ++++++++++++++++++- 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/runtime/astar/src/precompiles.rs b/runtime/astar/src/precompiles.rs index 3845c68fd..ffe0e2cbd 100644 --- a/runtime/astar/src/precompiles.rs +++ b/runtime/astar/src/precompiles.rs @@ -60,6 +60,7 @@ impl Contains for WhitelistedCalls { calls.iter().all(|call| WhitelistedCalls::contains(call)) } RuntimeCall::DappsStaking(_) => true, + RuntimeCall::Assets(pallet_assets::Call::transfer { .. }) => true, _ => false, } } diff --git a/runtime/local/src/precompiles.rs b/runtime/local/src/precompiles.rs index 6bf29d17f..b2ccb203b 100644 --- a/runtime/local/src/precompiles.rs +++ b/runtime/local/src/precompiles.rs @@ -56,6 +56,7 @@ impl Contains for WhitelistedCalls { | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { calls.iter().all(|call| WhitelistedCalls::contains(call)) } + RuntimeCall::Assets(pallet_assets::Call::transfer { .. }) => true, RuntimeCall::DappsStaking(_) => true, _ => false, } diff --git a/runtime/shibuya/src/precompiles.rs b/runtime/shibuya/src/precompiles.rs index 0965bcd57..d87b7e31f 100644 --- a/runtime/shibuya/src/precompiles.rs +++ b/runtime/shibuya/src/precompiles.rs @@ -59,6 +59,7 @@ impl Contains for WhitelistedCalls { | RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => { calls.iter().all(|call| WhitelistedCalls::contains(call)) } + RuntimeCall::Assets(pallet_assets::Call::transfer { .. }) => true, RuntimeCall::DappsStaking(_) => true, _ => false, } diff --git a/runtime/shiden/src/precompiles.rs b/runtime/shiden/src/precompiles.rs index 7dde89084..9e714eceb 100644 --- a/runtime/shiden/src/precompiles.rs +++ b/runtime/shiden/src/precompiles.rs @@ -59,6 +59,7 @@ impl Contains for WhitelistedCalls { calls.iter().all(|call| WhitelistedCalls::contains(call)) } RuntimeCall::DappsStaking(_) => true, + RuntimeCall::Assets(pallet_assets::Call::transfer { .. }) => true, _ => false, } } diff --git a/tests/integration/src/dispatch_precompile_filter.rs b/tests/integration/src/dispatch_precompile_filter.rs index 61a42f6a4..1099d592f 100644 --- a/tests/integration/src/dispatch_precompile_filter.rs +++ b/tests/integration/src/dispatch_precompile_filter.rs @@ -25,6 +25,7 @@ use frame_support::{ traits::Contains, }; use pallet_evm_precompile_dispatch::DispatchValidateT; +use parity_scale_codec::Compact; /// Whitelisted Calls are defined in the runtime #[test] @@ -77,22 +78,38 @@ fn filter_rejects_non_whitelisted_batch_calls() { #[test] fn filter_accepts_whitelisted_calls() { ExtBuilder::default().build().execute_with(|| { + // Dappstaking call works let contract = SmartContract::Evm(H160::repeat_byte(0x01)); let stake_call = RuntimeCall::DappsStaking(DappStakingCall::Call::claim_staker { contract_id: contract.clone(), }); assert!(WhitelistedCalls::contains(&stake_call)); + + // Pallet::Assets transfer call works + let transfer_call = RuntimeCall::Assets(pallet_assets::Call::transfer { + id: Compact(0), + target: MultiAddress::Address20(H160::repeat_byte(0x01).into()), + amount: 100, + }); + assert!(WhitelistedCalls::contains(&transfer_call)); }); } #[test] fn filter_rejects_non_whitelisted_calls() { ExtBuilder::default().build().execute_with(|| { + // Random call from non whitelisted pallet doesn't work let transfer_call = RuntimeCall::Balances(BalancesCall::transfer { dest: MultiAddress::Id(CAT), value: 100_000_000_000, }); assert!(!WhitelistedCalls::contains(&transfer_call)); + + // Only `transfer` call from pallet assets work + // Other random call from Pallet Assets doesn't work + let thaw_asset_call = + RuntimeCall::Assets(pallet_assets::Call::thaw_asset { id: Compact(0) }); + assert!(!WhitelistedCalls::contains(&thaw_asset_call)); }) } @@ -106,8 +123,13 @@ fn filter_accepts_whitelisted_batch_all_calls() { let inner_call2 = RuntimeCall::DappsStaking(DappStakingCall::Call::claim_staker { contract_id: contract.clone(), }); + let transfer_call = RuntimeCall::Assets(pallet_assets::Call::transfer { + id: Compact(0), + target: MultiAddress::Address20(H160::repeat_byte(0x01).into()), + amount: 100, + }); let call = RuntimeCall::Utility(UtilityCall::batch_all { - calls: vec![inner_call1, inner_call2], + calls: vec![inner_call1, inner_call2, transfer_call], }); assert!(WhitelistedCalls::contains(&call)); }); From 5d805141698853fedbf8c884296939a88720fee8 Mon Sep 17 00:00:00 2001 From: Deepanshu Hooda Date: Wed, 27 Sep 2023 11:35:42 +0530 Subject: [PATCH 15/15] fmt --- tests/integration/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/src/lib.rs b/tests/integration/src/lib.rs index 3f9bfbba8..d43b84541 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(any(feature = "shibuya", feature = "shiden", feature = "astar"))] -mod dispatch_precompile_filter; #[cfg(feature = "shibuya")] mod account; +#[cfg(any(feature = "shibuya", feature = "shiden", feature = "astar"))] +mod dispatch_precompile_filter;