diff --git a/polkadot/runtime/common/src/integration_tests.rs b/polkadot/runtime/common/src/integration_tests.rs index 2bf21bbde9..fe2f7d8365 100644 --- a/polkadot/runtime/common/src/integration_tests.rs +++ b/polkadot/runtime/common/src/integration_tests.rs @@ -930,8 +930,18 @@ fn basic_swap_works() { // Deposit is appropriately taken // ----------------------------------------- para deposit --- crowdloan - assert_eq!(Balances::reserved_balance(&account_id(1)), (500 + 10 * 2 * 1) + 100); - assert_eq!(Balances::reserved_balance(&account_id(2)), 500 + 20 * 2 * 1); + let crowdloan_deposit = 100; + let para_id_deposit = ::ParaDeposit::get(); + let code_deposit = configuration::Pallet::::config().max_code_size * + ::DataDepositPerByte::get(); + + // Para 2000 has a genesis head size of 10. + assert_eq!( + Balances::reserved_balance(&account_id(1)), + crowdloan_deposit + para_id_deposit + code_deposit + 10 + ); + // Para 2001 has a genesis head size of 20. + assert_eq!(Balances::reserved_balance(&account_id(2)), para_id_deposit + code_deposit + 20); assert_eq!(Balances::reserved_balance(&crowdloan_account), total); // Crowdloan is appropriately set assert!(Crowdloan::funds(ParaId::from(2000)).is_some()); @@ -973,8 +983,8 @@ fn basic_swap_works() { // Deregister on-demand parachain assert_ok!(Registrar::deregister(para_origin(2000).into(), ParaId::from(2000))); // Correct deposit is unreserved - assert_eq!(Balances::reserved_balance(&account_id(1)), 100); // crowdloan deposit left over - assert_eq!(Balances::reserved_balance(&account_id(2)), 500 + 20 * 2 * 1); + assert_eq!(Balances::reserved_balance(&account_id(1)), crowdloan_deposit); + assert_eq!(Balances::reserved_balance(&account_id(2)), para_id_deposit + code_deposit + 20); // Crowdloan ownership is swapped assert!(Crowdloan::funds(ParaId::from(2000)).is_none()); assert!(Crowdloan::funds(ParaId::from(2001)).is_some()); @@ -1005,7 +1015,7 @@ fn basic_swap_works() { // Dissolve returns the balance of the person who put a deposit for crowdloan assert_ok!(Crowdloan::dissolve(signed(1), ParaId::from(2001))); assert_eq!(Balances::reserved_balance(&account_id(1)), 0); - assert_eq!(Balances::reserved_balance(&account_id(2)), 500 + 20 * 2 * 1); + assert_eq!(Balances::reserved_balance(&account_id(2)), para_id_deposit + code_deposit + 20); // Final deregister sets everything back to the start assert_ok!(Registrar::deregister(para_origin(2001).into(), ParaId::from(2001))); diff --git a/polkadot/runtime/common/src/paras_registrar/mod.rs b/polkadot/runtime/common/src/paras_registrar/mod.rs index a3bdc1b1b0..a41f338e79 100644 --- a/polkadot/runtime/common/src/paras_registrar/mod.rs +++ b/polkadot/runtime/common/src/paras_registrar/mod.rs @@ -239,7 +239,13 @@ pub mod pallet { /// - `validation_code`: The initial validation code of the parachain/thread. /// /// ## Deposits/Fees - /// The origin signed account must reserve a corresponding deposit for the registration. + /// The account with the originating signature must reserve a deposit. + /// + /// The deposit is required to cover the costs associated with storing the genesis head + /// data and the validation code. + /// This accounts for the potential to store validation code of a size up to the + /// `max_code_size`, as defined in the configuration pallet + /// /// Anything already reserved previously for this para ID is accounted for. /// /// ## Events @@ -661,7 +667,7 @@ impl Pallet { let per_byte_fee = T::DataDepositPerByte::get(); let deposit = T::ParaDeposit::get() .saturating_add(per_byte_fee.saturating_mul((genesis_head.0.len() as u32).into())) - .saturating_add(per_byte_fee.saturating_mul((validation_code.0.len() as u32).into())); + .saturating_add(per_byte_fee.saturating_mul(config.max_code_size.into())); Ok((ParaGenesisArgs { genesis_head, validation_code, para_kind }, deposit)) } @@ -1013,10 +1019,16 @@ mod tests { run_to_session(START_SESSION_INDEX + 2); assert!(Parachains::is_parathread(para_id)); + // Even though the registered validation code has a smaller size than the maximum the + // para manager's deposit is reserved as though they registered the maximum-sized code. + // Consequently, they can upgrade their code to the maximum size at any point without + // additional cost. + let validation_code_deposit = + max_code_size() as BalanceOf * ::DataDepositPerByte::get(); + let head_deposit = 32 * ::DataDepositPerByte::get(); assert_eq!( Balances::reserved_balance(&1), - ::ParaDeposit::get() + - 64 * ::DataDepositPerByte::get() + ::ParaDeposit::get() + head_deposit + validation_code_deposit ); }); } diff --git a/prdoc/pr_3020.prdoc b/prdoc/pr_3020.prdoc new file mode 100644 index 0000000000..b605a2f2f0 --- /dev/null +++ b/prdoc/pr_3020.prdoc @@ -0,0 +1,14 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Para registration deposit covering max code size + +doc: + - audience: Runtime User + description: | + With this PR all newly registered parachains must pay a deposit equivalent to the cost of + registering validation code of the maximum size. Consequently, they can upgrade their code + to the maximum size at any point without additional cost. + +crates: + - name: polkadot-runtime-common