From 9b09f8fbf0bef8e14d2cfb5cd3e02ebcf97eb94d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Thei=C3=9Fen?= Date: Wed, 15 Oct 2025 12:13:47 +0300 Subject: [PATCH 1/2] Lower the deposit costs for child trie items --- .../assets/asset-hub-westend/src/lib.rs | 2 ++ .../runtimes/testing/penpal/src/lib.rs | 2 ++ substrate/bin/node/runtime/src/lib.rs | 2 ++ substrate/frame/revive/src/lib.rs | 15 +++++++++++++++ substrate/frame/revive/src/storage.rs | 17 +++++++++-------- substrate/frame/revive/src/storage/meter.rs | 2 +- substrate/frame/revive/src/tests.rs | 1 + substrate/frame/revive/src/vm/mod.rs | 10 +++++----- 8 files changed, 37 insertions(+), 14 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 0dbe4a13656c7..1572d68cd0b17 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1172,6 +1172,7 @@ impl pallet_xcm_bridge_hub_router::Config for Runtime parameter_types! { pub const DepositPerItem: Balance = deposit(1, 0); + pub const DepositPerChildTrieItem: Balance = deposit(1, 0) / 100; pub const DepositPerByte: Balance = deposit(0, 1); pub CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(30); pub const MaxEthExtrinsicWeight: FixedU128 = FixedU128::from_rational(1,2); @@ -1185,6 +1186,7 @@ impl pallet_revive::Config for Runtime { type RuntimeCall = RuntimeCall; type RuntimeOrigin = RuntimeOrigin; type DepositPerItem = DepositPerItem; + type DepositPerChildTrieItem = DepositPerChildTrieItem; type DepositPerByte = DepositPerByte; type WeightInfo = pallet_revive::weights::SubstrateWeight; type Precompiles = ( diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index a5808c05ef74e..2b2f396dd20f1 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -806,6 +806,7 @@ impl pallet_asset_tx_payment::Config for Runtime { parameter_types! { pub const DepositPerItem: Balance = 0; + pub const DepositPerChildTrieItem: Balance = 0; pub const DepositPerByte: Balance = 0; pub CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(30); pub const MaxEthExtrinsicWeight: FixedU128 = FixedU128::from_rational(1,2); @@ -819,6 +820,7 @@ impl pallet_revive::Config for Runtime { type RuntimeCall = RuntimeCall; type RuntimeOrigin = RuntimeOrigin; type DepositPerItem = DepositPerItem; + type DepositPerChildTrieItem = DepositPerChildTrieItem; type DepositPerByte = DepositPerByte; type WeightInfo = pallet_revive::weights::SubstrateWeight; type Precompiles = (); diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 01d990c62a0fa..c5c400ff25198 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1397,6 +1397,7 @@ impl pallet_tips::Config for Runtime { parameter_types! { pub const DepositPerItem: Balance = deposit(1, 0); + pub const DepositPerChildTrieItem: Balance = deposit(1, 0) / 100; pub const DepositPerByte: Balance = deposit(0, 1); pub const DefaultDepositLimit: Balance = deposit(1024, 1024 * 1024); pub Schedule: pallet_contracts::Schedule = Default::default(); @@ -1454,6 +1455,7 @@ impl pallet_revive::Config for Runtime { type RuntimeCall = RuntimeCall; type RuntimeOrigin = RuntimeOrigin; type DepositPerItem = DepositPerItem; + type DepositPerChildTrieItem = DepositPerChildTrieItem; type DepositPerByte = DepositPerByte; type WeightInfo = pallet_revive::weights::SubstrateWeight; type Precompiles = diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 4d97ca194c86a..9b1c8fa538411 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -218,6 +218,19 @@ pub mod pallet { #[pallet::no_default_bounds] type DepositPerItem: Get>; + /// The amount of balance a caller has to pay for each child trie storage item. + /// + /// Those are the items created by a contract. In Solidity each value is a single + /// storage item. This is why we need to set a lower value here than for the main + /// trie items. Otherwise the storage deposit is too high. + /// + /// # Note + /// + /// It is safe to change this value on a live chain as all refunds are pro rata. + #[pallet::constant] + #[pallet::no_default_bounds] + type DepositPerChildTrieItem: Get>; + /// The percentage of the storage deposit that should be held for using a code hash. /// Instantiating a contract, protects the code from being removed. In order to prevent /// abuse these actions are protected with a percentage of the code deposit. @@ -339,6 +352,7 @@ pub mod pallet { parameter_types! { pub const DepositPerItem: Balance = deposit(1, 0); + pub const DepositPerChildTrieItem: Balance = deposit(1, 0) / 100; pub const DepositPerByte: Balance = deposit(0, 1); pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0); pub const MaxEthExtrinsicWeight: FixedU128 = FixedU128::from_rational(1, 2); @@ -381,6 +395,7 @@ pub mod pallet { type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; type DepositPerByte = DepositPerByte; type DepositPerItem = DepositPerItem; + type DepositPerChildTrieItem = DepositPerChildTrieItem; type Time = Self; type UnsafeUnstableInterface = ConstBool; type AllowEVMBytecode = ConstBool; diff --git a/substrate/frame/revive/src/storage.rs b/substrate/frame/revive/src/storage.rs index b8b02bc717736..0033142ec5754 100644 --- a/substrate/frame/revive/src/storage.rs +++ b/substrate/frame/revive/src/storage.rs @@ -22,7 +22,6 @@ pub mod meter; use crate::{ address::AddressMapper, exec::{AccountIdOf, Key}, - storage::meter::Diff, tracing::if_tracing, weights::WeightInfo, AccountInfoOf, BalanceOf, BalanceWithDust, Config, DeletionQueue, DeletionQueueCounter, Error, @@ -357,13 +356,15 @@ impl ContractInfo { /// the deposit paid to upload the contract's code. It also depends on the size of immutable /// storage which is also changed when the code hash of a contract is changed. pub fn update_base_deposit(&mut self, code_deposit: BalanceOf) -> BalanceOf { - let contract_deposit = Diff { - bytes_added: (self.encoded_size() as u32).saturating_add(self.immutable_data_len), - items_added: if self.immutable_data_len == 0 { 1 } else { 2 }, - ..Default::default() - } - .update_contract::(None) - .charge_or_zero(); + let contract_deposit = { + let bytes_added: u32 = + (self.encoded_size() as u32).saturating_add(self.immutable_data_len); + let items_added: u32 = if self.immutable_data_len == 0 { 1 } else { 2 }; + + T::DepositPerByte::get() + .saturating_mul(bytes_added.into()) + .saturating_add(T::DepositPerItem::get().saturating_mul(items_added.into())) + }; // Instantiating the contract prevents its code to be deleted, therefore the base deposit // includes a fraction (`T::CodeHashLockupDepositPercent`) of the original storage deposit diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index 22acb62e88c59..aabcb0f8423d3 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -137,7 +137,7 @@ impl Diff { /// this information from the passed `info`. pub fn update_contract(&self, info: Option<&mut ContractInfo>) -> DepositOf { let per_byte = T::DepositPerByte::get(); - let per_item = T::DepositPerItem::get(); + let per_item = T::DepositPerChildTrieItem::get(); let bytes_added = self.bytes_added.saturating_sub(self.bytes_removed); let items_added = self.items_added.saturating_sub(self.items_removed); let mut bytes_deposit = Deposit::Charge(per_byte.saturating_mul((bytes_added).into())); diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index 17d357ba7c042..817ff9b0b44f9 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -382,6 +382,7 @@ impl Config for Test { type Currency = Balances; type DepositPerByte = DepositPerByte; type DepositPerItem = DepositPerItem; + type DepositPerChildTrieItem = DepositPerItem; type UnsafeUnstableInterface = UnstableInterface; type AllowEVMBytecode = AllowEvmBytecode; type UploadOrigin = EnsureAccount; diff --git a/substrate/frame/revive/src/vm/mod.rs b/substrate/frame/revive/src/vm/mod.rs index 6e1fc9853f590..7b543669d6aea 100644 --- a/substrate/frame/revive/src/vm/mod.rs +++ b/substrate/frame/revive/src/vm/mod.rs @@ -28,7 +28,7 @@ use crate::{ exec::{ExecResult, Executable, ExportedFunction, Ext}, frame_support::{ensure, error::BadOrigin, traits::tokens::Restriction}, gas::{GasMeter, Token}, - storage::meter::{Diff, NestedMeter}, + storage::meter::NestedMeter, weights::WeightInfo, AccountIdOf, BalanceOf, CodeInfoOf, CodeRemoved, Config, Error, ExecConfig, ExecError, HoldReason, Pallet, PristineCode, StorageDeposit, Weight, LOG_TARGET, @@ -44,7 +44,7 @@ use frame_support::{ }; use pallet_revive_uapi::ReturnErrorCode; use sp_core::{Get, H256}; -use sp_runtime::DispatchError; +use sp_runtime::{DispatchError, Saturating}; /// Validated Vm module ready for execution. /// This data structure is immutable once created and stored. @@ -109,9 +109,9 @@ pub struct CodeInfo { /// Calculate the deposit required for storing code and its metadata. pub fn calculate_code_deposit(code_len: u32) -> BalanceOf { let bytes_added = code_len.saturating_add(>::max_encoded_len() as u32); - Diff { bytes_added, items_added: 2, ..Default::default() } - .update_contract::(None) - .charge_or_zero() + T::DepositPerByte::get() + .saturating_mul(bytes_added.into()) + .saturating_add(T::DepositPerItem::get().saturating_mul(2u32.into())) } impl ExportedFunction { From 5bfd920c4341bc70d00430d0f5c2dccdecbb385d Mon Sep 17 00:00:00 2001 From: "cmd[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 10:06:39 +0000 Subject: [PATCH 2/2] Update from github-actions[bot] running command 'prdoc --audience runtime_dev --audience runtime_user --bump major' --- prdoc/pr_10027.prdoc | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 prdoc/pr_10027.prdoc diff --git a/prdoc/pr_10027.prdoc b/prdoc/pr_10027.prdoc new file mode 100644 index 0000000000000..b355836f77fce --- /dev/null +++ b/prdoc/pr_10027.prdoc @@ -0,0 +1,11 @@ +title: 'pallet_revive: Lower the deposit costs for child trie items' +doc: +- audience: Runtime User + description: Fixes https://github.com/paritytech/polkadot-sdk/issues/9246 +crates: +- name: asset-hub-westend-runtime + bump: major +- name: penpal-runtime + bump: major +- name: pallet-revive + bump: major