From dfe492d7c316775d095eed3e6292bf946020b05a Mon Sep 17 00:00:00 2001 From: UtkarshBhardwaj007 Date: Wed, 30 Apr 2025 12:01:19 +0100 Subject: [PATCH 1/9] add poke_deposit extrinsic to pallet-bounties --- .../rococo/src/weights/pallet_bounties.rs | 6 + substrate/frame/bounties/src/benchmarking.rs | 26 ++ substrate/frame/bounties/src/lib.rs | 83 ++++- substrate/frame/bounties/src/tests.rs | 330 +++++++++++++++++- substrate/frame/bounties/src/weights.rs | 11 + 5 files changed, 452 insertions(+), 4 deletions(-) diff --git a/polkadot/runtime/rococo/src/weights/pallet_bounties.rs b/polkadot/runtime/rococo/src/weights/pallet_bounties.rs index ee903a2f4e33a..6c9902ea832d3 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_bounties.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_bounties.rs @@ -248,4 +248,10 @@ impl pallet_bounties::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(b.into()))) .saturating_add(Weight::from_parts(0, 5206).saturating_mul(b.into())) } + fn poke_deposit() -> Weight { + Weight::from_parts(15_756_000, 0) + .saturating_add(Weight::from_parts(0, 3642)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/substrate/frame/bounties/src/benchmarking.rs b/substrate/frame/bounties/src/benchmarking.rs index ca678057a9022..18003e5c6ea56 100644 --- a/substrate/frame/bounties/src/benchmarking.rs +++ b/substrate/frame/bounties/src/benchmarking.rs @@ -271,5 +271,31 @@ benchmarks_instance_pallet! { } } + poke_deposit { + // Create a bounty + let (caller, _, _, value, reason) = setup_bounty::(0, 5); // 5 bytes description + Bounties::::propose_bounty(RawOrigin::Signed(caller.clone()).into(), value, reason)?; + let bounty_id = BountyCount::::get() - 1; + let old_deposit = T::Currency::reserved_balance(&caller); + // Modify the description to be maximum length + let max_description: Vec = vec![0; T::MaximumReasonLength::get() as usize]; + let bounded_description: BoundedVec = max_description.try_into() + .expect("description length was set to T::MaximumReasonLength; qed"); + BountyDescriptions::::insert(bounty_id, bounded_description); + + // Ensure caller has enough balance for new deposit + let new_deposit = T::BountyDepositBase::get() + .saturating_add(T::DataDepositPerByte::get().saturating_mul((T::MaximumReasonLength::get()).into())); + let required_balance = new_deposit.saturating_add(minimum_balance::()); + T::Currency::make_free_balance_be(&caller, required_balance); + + }: _(RawOrigin::Signed(caller.clone()), bounty_id) + verify { + let bounty = crate::Bounties::::get(bounty_id).unwrap(); + assert_eq!(bounty.bond, new_deposit); + assert_eq!(T::Currency::reserved_balance(&caller), new_deposit); + assert_last_event::(Event::DepositPoked { bounty_id, proposer: caller, old_deposit: old_deposit, new_deposit: new_deposit }.into()); + } + impl_benchmark_test_suite!(Bounties, crate::tests::ExtBuilder::default().build(), crate::tests::Test) } diff --git a/substrate/frame/bounties/src/lib.rs b/substrate/frame/bounties/src/lib.rs index e95fd6addd551..5380237145b8e 100644 --- a/substrate/frame/bounties/src/lib.rs +++ b/substrate/frame/bounties/src/lib.rs @@ -299,6 +299,8 @@ pub mod pallet { HasActiveChildBounty, /// Too many approvals are already queued. TooManyQueued, + /// User is not the proposer of the bounty. + NotProposer, } #[pallet::event] @@ -326,6 +328,13 @@ pub mod pallet { CuratorUnassigned { bounty_id: BountyIndex }, /// A bounty curator is accepted. CuratorAccepted { bounty_id: BountyIndex, curator: T::AccountId }, + /// A bounty deposit has been poked. + DepositPoked { + bounty_id: BountyIndex, + proposer: T::AccountId, + old_deposit: BalanceOf, + new_deposit: BalanceOf, + }, } /// Number of bounty proposals that have been made. @@ -885,6 +894,34 @@ pub mod pallet { Ok(()) } + + /// Poke the deposit reserved for creating a bounty proposal. + /// + /// This can be used by accounts to possibly lower their locked amount. + /// + /// The dispatch origin for this call must be _Signed_ and must be the proposer of the bounty. + /// + /// Parameters: + /// - `bounty_id`: The bounty id for which to adjust the deposit. + /// + /// If the deposit is updated, the difference will be reserved/unreserved from the proposer's + /// account. + /// + /// The transaction is made free if the deposit is updated and paid otherwise. + /// + /// Emits `DepositPoked` if the deposit is updated. + #[pallet::call_index(10)] + #[pallet::weight(>::WeightInfo::poke_deposit())] + pub fn poke_deposit( + origin: OriginFor, + #[pallet::compact] bounty_id: BountyIndex, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + + let deposit_updated = Self::poke_bounty_deposit(bounty_id, who)?; + + Ok(if deposit_updated { Pays::No } else { Pays::Yes }.into()) + } } #[pallet::hooks] @@ -986,8 +1023,7 @@ impl, I: 'static> Pallet { let index = BountyCount::::get(); // reserve deposit for new bounty - let bond = T::BountyDepositBase::get() + - T::DataDepositPerByte::get() * (bounded_description.len() as u32).into(); + let bond = Self::calculate_bounty_deposit(&bounded_description); T::Currency::reserve(&proposer, bond) .map_err(|_| Error::::InsufficientProposersBalance)?; @@ -1009,6 +1045,49 @@ impl, I: 'static> Pallet { Ok(()) } + + /// Helper function to calculate the bounty storage deposit. + fn calculate_bounty_deposit(description: &BoundedVec) -> BalanceOf { + T::BountyDepositBase::get() + T::DataDepositPerByte::get() * (description.len() as u32).into() + } + + /// Helper function to poke the deposit reserved for proposing a bounty. + /// + /// Returns true if the deposit was updated and false otherwise. + fn poke_bounty_deposit(bounty_id: BountyIndex, who: T::AccountId) -> Result { + let mut bounty = Bounties::::get(bounty_id).ok_or(Error::::InvalidIndex)?; + let bounty_description = BountyDescriptions::::get(bounty_id).ok_or(Error::::InvalidIndex)?; + // ensure that the bounty status is proposed. + ensure!(bounty.status == BountyStatus::Proposed, Error::::UnexpectedStatus); + + // ensure that bounty proposer is the origin for this call. + ensure!(bounty.proposer == who, Error::::NotProposer); + + let new_bond = Self::calculate_bounty_deposit(&bounty_description); + let old_bond = bounty.bond; + if new_bond == old_bond { + return Ok(false); + } + if new_bond > old_bond { + let extra = new_bond.saturating_sub(old_bond); + T::Currency::reserve(&who, extra)?; + } else { + let excess = old_bond.saturating_sub(new_bond); + let remaining_unreserved = T::Currency::unreserve(&who, excess); + if !remaining_unreserved.is_zero() { + defensive!( + "Failed to unreserve full amount. (Requested, Actual)", + (excess, excess.saturating_sub(remaining_unreserved)) + ); + } + } + bounty.bond = new_bond; + Bounties::::insert(bounty_id, &bounty); + + Self::deposit_event(Event::::DepositPoked { bounty_id, proposer: who, old_deposit: old_bond, new_deposit: new_bond }); + + Ok(true) + } } impl, I: 'static> pallet_treasury::SpendFunds for Pallet { diff --git a/substrate/frame/bounties/src/tests.rs b/substrate/frame/bounties/src/tests.rs index 4b74c4162c30b..31fa2bdeda0d1 100644 --- a/substrate/frame/bounties/src/tests.rs +++ b/substrate/frame/bounties/src/tests.rs @@ -138,6 +138,7 @@ parameter_types! { pub const CuratorDepositMax: Balance = 1_000; pub const CuratorDepositMin: Balance = 3; pub static BountyUpdatePeriod: u64 = 20; + pub static DataDepositPerByte: u64 = 1; } impl Config for Test { @@ -149,7 +150,7 @@ impl Config for Test { type CuratorDepositMax = CuratorDepositMax; type CuratorDepositMin = CuratorDepositMin; type BountyValueMinimum = ConstU64<1>; - type DataDepositPerByte = ConstU64<1>; + type DataDepositPerByte = DataDepositPerByte; type MaximumReasonLength = ConstU32<16384>; type WeightInfo = (); type ChildBountyManager = (); @@ -165,7 +166,7 @@ impl Config for Test { type CuratorDepositMax = CuratorDepositMax; type CuratorDepositMin = CuratorDepositMin; type BountyValueMinimum = ConstU64<1>; - type DataDepositPerByte = ConstU64<1>; + type DataDepositPerByte = DataDepositPerByte; type MaximumReasonLength = ConstU32<16384>; type WeightInfo = (); type ChildBountyManager = (); @@ -1481,3 +1482,328 @@ fn accept_curator_sets_update_due_correctly() { ); }); } + +#[test] +fn poke_deposit_fails_for_insufficient_balance() { + ExtBuilder::default().build_and_execute(|| { + // Create a bounty + assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec())); + + // BountyDepositBase (80) + DataDepositPerByte (1) * description.len() (5) + let deposit = 85; + + // Verify initial state + assert_eq!(Balances::reserved_balance(0), deposit); + assert_eq!(Balances::free_balance(0), 100 - deposit); + assert_eq!(last_event(), BountiesEvent::BountyProposed { index: 0 }); + assert_eq!( + pallet_bounties::Bounties::::get(0).unwrap(), + Bounty { + proposer: 0, + value: 50, + fee: 0, + curator_deposit: 0, + bond: deposit, + status: BountyStatus::Proposed, + } + ); + assert_eq!( + pallet_bounties::BountyDescriptions::::get(0).unwrap(), + b"12345".to_vec() + ); + assert_eq!(pallet_bounties::BountyCount::::get(), 1); + + // Increase the DataDepositPerByte to be more than the total balance of the proposer + DataDepositPerByte::set(20); + + // Poke deposit should fail due to insufficient balance + assert_noop!( + Bounties::poke_deposit(RuntimeOrigin::signed(0), 0), + pallet_balances::Error::::InsufficientBalance + ); + }); +} + +#[test] +fn poke_deposit_fails_for_unsigned_origin() { + ExtBuilder::default().build_and_execute(|| { + assert_noop!(Bounties::poke_deposit(RuntimeOrigin::none(), 0), DispatchError::BadOrigin); + }); +} + +#[test] +fn poke_deposit_fails_for_non_existent_bounty() { + ExtBuilder::default().build_and_execute(|| { + assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(0), 0), Error::::InvalidIndex); + }); +} + +#[test] +fn poke_deposit_fails_for_non_proposer() { + ExtBuilder::default().build_and_execute(|| { + assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec())); + + // BountyDepositBase (80) + DataDepositPerByte (1) * description.len() (5) + let deposit = 85; + + // Verify initial state + assert_eq!(Balances::reserved_balance(0), deposit); + assert_eq!(Balances::reserved_balance(1), 0); + assert_eq!(Balances::free_balance(0), 100 - deposit); + assert_eq!(last_event(), BountiesEvent::BountyProposed { index: 0 }); + assert_eq!( + pallet_bounties::Bounties::::get(0).unwrap(), + Bounty { + proposer: 0, + value: 50, + fee: 0, + curator_deposit: 0, + bond: deposit, + status: BountyStatus::Proposed, + } + ); + assert_eq!( + pallet_bounties::BountyDescriptions::::get(0).unwrap(), + b"12345".to_vec() + ); + assert_eq!(pallet_bounties::BountyCount::::get(), 1); + + // Poke deposit should fail due to non-proposer + assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(1), 0), Error::::NotProposer); + }); +} + +#[test] +fn poke_deposit_fails_for_any_status_other_than_proposed() { + ExtBuilder::default().build_and_execute(|| { + let bounty_id = 0; + let proposer = 0; + let curator = 4; + let deposit = 85; + let mut bounty = Bounty { + proposer: proposer, + value: 50, + fee: 0, + curator_deposit: 0, + bond: deposit, + status: BountyStatus::Proposed, + }; + assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(proposer), 50, b"12345".to_vec())); + + // Verify initial state + assert_eq!(Balances::reserved_balance(proposer), deposit); + assert_eq!(Balances::reserved_balance(1), 0); + assert_eq!(Balances::free_balance(proposer), 100 - deposit); + assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); + assert_eq!( + pallet_bounties::Bounties::::get(0).unwrap(), + bounty + ); + assert_eq!( + pallet_bounties::BountyDescriptions::::get(0).unwrap(), + b"12345".to_vec() + ); + assert_eq!(pallet_bounties::BountyCount::::get(), 1); + + // Change status to approved + bounty.status = BountyStatus::Approved; + pallet_bounties::Bounties::::insert(bounty_id, &bounty); + // Poke deposit should fail due to invalid status + assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), Error::::UnexpectedStatus); + + // Change status to funded + bounty.status = BountyStatus::Funded; + pallet_bounties::Bounties::::insert(bounty_id, &bounty); + // Poke deposit should fail due to invalid status + assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), Error::::UnexpectedStatus); + + // Change status to curator proposed + bounty.status = BountyStatus::CuratorProposed { curator }; + pallet_bounties::Bounties::::insert(bounty_id, &bounty); + // Poke deposit should fail due to invalid status + assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), Error::::UnexpectedStatus); + + // Change status to active + bounty.status = BountyStatus::Active { curator, update_due: 24 }; + pallet_bounties::Bounties::::insert(bounty_id, &bounty); + // Poke deposit should fail due to invalid status + assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), Error::::UnexpectedStatus); + + // Change status to PendingPayout + bounty.status = BountyStatus::PendingPayout { curator, beneficiary: 0, unlock_at: 24 }; + pallet_bounties::Bounties::::insert(bounty_id, &bounty); + // Poke deposit should fail due to invalid status + assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), Error::::UnexpectedStatus); + + // Change status to ApprovedWithCurator + bounty.status = BountyStatus::ApprovedWithCurator { curator }; + pallet_bounties::Bounties::::insert(bounty_id, &bounty); + // Poke deposit should fail due to invalid status + assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), Error::::UnexpectedStatus); + }); +} + +#[test] +fn poke_deposit_works_and_charges_fee_for_unchanged_deposit() { + ExtBuilder::default().build_and_execute(|| { + let bounty_id = 0; + let proposer = 0; + let deposit = 85; + let bounty = Bounty { + proposer: proposer, + value: 50, + fee: 0, + curator_deposit: 0, + bond: deposit, + status: BountyStatus::Proposed, + }; + assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(proposer), 50, b"12345".to_vec())); + + // Verify initial state + assert_eq!(Balances::reserved_balance(proposer), deposit); + assert_eq!(Balances::free_balance(proposer), 100 - deposit); + assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); + assert_eq!( + pallet_bounties::Bounties::::get(0).unwrap(), + bounty + ); + assert_eq!( + pallet_bounties::BountyDescriptions::::get(0).unwrap(), + b"12345".to_vec() + ); + assert_eq!(pallet_bounties::BountyCount::::get(), 1); + + // Poke deposit should charge fee + let result = Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id); + assert_ok!(result.as_ref()); + assert_eq!(result.unwrap(), Pays::Yes.into()); + + // Verify final state + assert_eq!(Balances::reserved_balance(proposer), deposit); + assert_eq!( + pallet_bounties::Bounties::::get(0).unwrap(), + bounty + ); + assert_eq!( + pallet_bounties::BountyDescriptions::::get(0).unwrap(), + b"12345".to_vec() + ); + assert_eq!(pallet_bounties::BountyCount::::get(), 1); + assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); + }); +} + +#[test] +fn poke_deposit_works_for_deposit_increase() { + ExtBuilder::default().build_and_execute(|| { + let bounty_id = 0; + let proposer = 0; + let deposit = 85; + let mut bounty = Bounty { + proposer: proposer, + value: 50, + fee: 0, + curator_deposit: 0, + bond: deposit, + status: BountyStatus::Proposed, + }; + assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(proposer), 50, b"12345".to_vec())); + + // Verify initial state + assert_eq!(Balances::reserved_balance(proposer), deposit); + assert_eq!(Balances::free_balance(proposer), 100 - deposit); + assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); + assert_eq!( + pallet_bounties::Bounties::::get(0).unwrap(), + bounty + ); + assert_eq!( + pallet_bounties::BountyDescriptions::::get(0).unwrap(), + b"12345".to_vec() + ); + assert_eq!(pallet_bounties::BountyCount::::get(), 1); + + // Increase the DataDepositPerByte + DataDepositPerByte::set(2); + // BountyDepositBase (80) + DataDepositPerByte (2) * description.len() (5) + let new_deposit = 90; + + // Poke deposit should increase reserve + let result = Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id); + assert_ok!(result.as_ref()); + assert_eq!(result.unwrap(), Pays::No.into()); + + // Verify final state + assert_eq!(Balances::reserved_balance(proposer), new_deposit); + assert_eq!(Balances::free_balance(proposer), 100 - new_deposit); + assert_eq!(last_event(), BountiesEvent::DepositPoked { bounty_id, proposer, old_deposit: deposit, new_deposit }); + bounty.bond = new_deposit; + assert_eq!( + pallet_bounties::Bounties::::get(0).unwrap(), + bounty + ); + assert_eq!( + pallet_bounties::BountyDescriptions::::get(0).unwrap(), + b"12345".to_vec() + ); + assert_eq!(pallet_bounties::BountyCount::::get(), 1); + }); +} + +#[test] +fn poke_deposit_works_for_deposit_decrease() { + ExtBuilder::default().build_and_execute(|| { + let bounty_id = 0; + let proposer = 0; + let deposit = 90; + let mut bounty = Bounty { + proposer: proposer, + value: 50, + fee: 0, + curator_deposit: 0, + bond: deposit, + status: BountyStatus::Proposed, + }; + DataDepositPerByte::set(2); + assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(proposer), 50, b"12345".to_vec())); + + // Verify initial state + assert_eq!(Balances::reserved_balance(proposer), deposit); + assert_eq!(Balances::free_balance(proposer), 100 - deposit); + assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); + assert_eq!( + pallet_bounties::Bounties::::get(0).unwrap(), + bounty + ); + assert_eq!( + pallet_bounties::BountyDescriptions::::get(0).unwrap(), + b"12345".to_vec() + ); + assert_eq!(pallet_bounties::BountyCount::::get(), 1); + + // Decrease the DataDepositPerByte + DataDepositPerByte::set(1); + // BountyDepositBase (80) + DataDepositPerByte (2) * description.len() (5) + let new_deposit = 85; + + // Poke deposit should increase reserve + let result = Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id); + assert_ok!(result.as_ref()); + assert_eq!(result.unwrap(), Pays::No.into()); + + // Verify final state + assert_eq!(Balances::reserved_balance(proposer), new_deposit); + assert_eq!(Balances::free_balance(proposer), 100 - new_deposit); + assert_eq!(last_event(), BountiesEvent::DepositPoked { bounty_id, proposer, old_deposit: deposit, new_deposit }); + bounty.bond = new_deposit; + assert_eq!( + pallet_bounties::Bounties::::get(0).unwrap(), + bounty + ); + assert_eq!( + pallet_bounties::BountyDescriptions::::get(0).unwrap(), + b"12345".to_vec() + ); + assert_eq!(pallet_bounties::BountyCount::::get(), 1); + }); +} diff --git a/substrate/frame/bounties/src/weights.rs b/substrate/frame/bounties/src/weights.rs index 4f0c50f519a13..a4476232a509b 100644 --- a/substrate/frame/bounties/src/weights.rs +++ b/substrate/frame/bounties/src/weights.rs @@ -84,6 +84,7 @@ pub trait WeightInfo { fn close_bounty_active() -> Weight; fn extend_bounty_expiry() -> Weight; fn spend_funds(b: u32, ) -> Weight; + fn poke_deposit() -> Weight; } /// Weights for `pallet_bounties` using the Substrate node and recommended hardware. @@ -274,6 +275,11 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(b.into()))) .saturating_add(Weight::from_parts(0, 5206).saturating_mul(b.into())) } + fn poke_deposit() -> Weight { + Weight::from_parts(13_905_000, 3642) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } } // For backwards compatibility and tests. @@ -463,4 +469,9 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(b.into()))) .saturating_add(Weight::from_parts(0, 5206).saturating_mul(b.into())) } + fn poke_deposit() -> Weight { + Weight::from_parts(13_905_000, 3642) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } } From 2fe2f72c07ab3e18acf74ed350991d0f0f13bcae Mon Sep 17 00:00:00 2001 From: "cmd[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 11:10:12 +0000 Subject: [PATCH 2/9] Update from github-actions[bot] running command 'prdoc' --- prdoc/pr_8382.prdoc | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 prdoc/pr_8382.prdoc diff --git a/prdoc/pr_8382.prdoc b/prdoc/pr_8382.prdoc new file mode 100644 index 0000000000000..3aad292fdb6ac --- /dev/null +++ b/prdoc/pr_8382.prdoc @@ -0,0 +1,26 @@ +title: add poke_deposit extrinsic to pallet-bounties +doc: +- audience: Todo + description: |- + # Description + + * This PR adds a new extrinsic `poke_deposit` to `pallet-bounties`. This extrinsic will be used to re-adjust the deposits made in the pallet to create a new bounty. + * Part of #5591 + + ## Review Notes + + * Added a new extrinsic `poke_deposit` in `pallet-bounties`. + * This extrinsic checks and adjusts the deposits made for creating a bounty. + * Added a new event `DepositPoked` to be emitted upon a successful call of the extrinsic. + * Although the immediate use of the extrinsic will be to give back some of the deposit after the AH-migration, the extrinsic is written such that it can work if the deposit decreases or increases (both). + * The call to the extrinsic would be `free` if an actual adjustment is made to the deposit and `paid` otherwise (when no deposit is changed). + * Added tests to test all scenarios. + * Added benchmarks + + ## TO-DOs + * [ ] Run CI cmd bot to benchmark +crates: +- name: rococo-runtime + bump: major +- name: pallet-bounties + bump: major From a8f94d5ed10eb11cf4ffff477293e99b21e23830 Mon Sep 17 00:00:00 2001 From: "cmd[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 11:10:51 +0000 Subject: [PATCH 3/9] Update from github-actions[bot] running command 'fmt' --- substrate/frame/bounties/src/lib.rs | 31 +++-- substrate/frame/bounties/src/tests.rs | 158 +++++++++++++------------- 2 files changed, 100 insertions(+), 89 deletions(-) diff --git a/substrate/frame/bounties/src/lib.rs b/substrate/frame/bounties/src/lib.rs index 5380237145b8e..397f845749452 100644 --- a/substrate/frame/bounties/src/lib.rs +++ b/substrate/frame/bounties/src/lib.rs @@ -899,13 +899,14 @@ pub mod pallet { /// /// This can be used by accounts to possibly lower their locked amount. /// - /// The dispatch origin for this call must be _Signed_ and must be the proposer of the bounty. + /// The dispatch origin for this call must be _Signed_ and must be the proposer of the + /// bounty. /// /// Parameters: /// - `bounty_id`: The bounty id for which to adjust the deposit. /// - /// If the deposit is updated, the difference will be reserved/unreserved from the proposer's - /// account. + /// If the deposit is updated, the difference will be reserved/unreserved from the + /// proposer's account. /// /// The transaction is made free if the deposit is updated and paid otherwise. /// @@ -1047,16 +1048,23 @@ impl, I: 'static> Pallet { } /// Helper function to calculate the bounty storage deposit. - fn calculate_bounty_deposit(description: &BoundedVec) -> BalanceOf { - T::BountyDepositBase::get() + T::DataDepositPerByte::get() * (description.len() as u32).into() + fn calculate_bounty_deposit( + description: &BoundedVec, + ) -> BalanceOf { + T::BountyDepositBase::get() + + T::DataDepositPerByte::get() * (description.len() as u32).into() } /// Helper function to poke the deposit reserved for proposing a bounty. - /// + /// /// Returns true if the deposit was updated and false otherwise. - fn poke_bounty_deposit(bounty_id: BountyIndex, who: T::AccountId) -> Result { + fn poke_bounty_deposit( + bounty_id: BountyIndex, + who: T::AccountId, + ) -> Result { let mut bounty = Bounties::::get(bounty_id).ok_or(Error::::InvalidIndex)?; - let bounty_description = BountyDescriptions::::get(bounty_id).ok_or(Error::::InvalidIndex)?; + let bounty_description = + BountyDescriptions::::get(bounty_id).ok_or(Error::::InvalidIndex)?; // ensure that the bounty status is proposed. ensure!(bounty.status == BountyStatus::Proposed, Error::::UnexpectedStatus); @@ -1084,7 +1092,12 @@ impl, I: 'static> Pallet { bounty.bond = new_bond; Bounties::::insert(bounty_id, &bounty); - Self::deposit_event(Event::::DepositPoked { bounty_id, proposer: who, old_deposit: old_bond, new_deposit: new_bond }); + Self::deposit_event(Event::::DepositPoked { + bounty_id, + proposer: who, + old_deposit: old_bond, + new_deposit: new_bond, + }); Ok(true) } diff --git a/substrate/frame/bounties/src/tests.rs b/substrate/frame/bounties/src/tests.rs index 31fa2bdeda0d1..7220a2ebd56e1 100644 --- a/substrate/frame/bounties/src/tests.rs +++ b/substrate/frame/bounties/src/tests.rs @@ -1507,10 +1507,7 @@ fn poke_deposit_fails_for_insufficient_balance() { status: BountyStatus::Proposed, } ); - assert_eq!( - pallet_bounties::BountyDescriptions::::get(0).unwrap(), - b"12345".to_vec() - ); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); assert_eq!(pallet_bounties::BountyCount::::get(), 1); // Increase the DataDepositPerByte to be more than the total balance of the proposer @@ -1534,7 +1531,10 @@ fn poke_deposit_fails_for_unsigned_origin() { #[test] fn poke_deposit_fails_for_non_existent_bounty() { ExtBuilder::default().build_and_execute(|| { - assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(0), 0), Error::::InvalidIndex); + assert_noop!( + Bounties::poke_deposit(RuntimeOrigin::signed(0), 0), + Error::::InvalidIndex + ); }); } @@ -1562,14 +1562,14 @@ fn poke_deposit_fails_for_non_proposer() { status: BountyStatus::Proposed, } ); - assert_eq!( - pallet_bounties::BountyDescriptions::::get(0).unwrap(), - b"12345".to_vec() - ); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); assert_eq!(pallet_bounties::BountyCount::::get(), 1); // Poke deposit should fail due to non-proposer - assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(1), 0), Error::::NotProposer); + assert_noop!( + Bounties::poke_deposit(RuntimeOrigin::signed(1), 0), + Error::::NotProposer + ); }); } @@ -1581,65 +1581,81 @@ fn poke_deposit_fails_for_any_status_other_than_proposed() { let curator = 4; let deposit = 85; let mut bounty = Bounty { - proposer: proposer, + proposer, value: 50, fee: 0, curator_deposit: 0, bond: deposit, status: BountyStatus::Proposed, }; - assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(proposer), 50, b"12345".to_vec())); + assert_ok!(Bounties::propose_bounty( + RuntimeOrigin::signed(proposer), + 50, + b"12345".to_vec() + )); // Verify initial state assert_eq!(Balances::reserved_balance(proposer), deposit); assert_eq!(Balances::reserved_balance(1), 0); assert_eq!(Balances::free_balance(proposer), 100 - deposit); assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); - assert_eq!( - pallet_bounties::Bounties::::get(0).unwrap(), - bounty - ); - assert_eq!( - pallet_bounties::BountyDescriptions::::get(0).unwrap(), - b"12345".to_vec() - ); + assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); assert_eq!(pallet_bounties::BountyCount::::get(), 1); // Change status to approved bounty.status = BountyStatus::Approved; pallet_bounties::Bounties::::insert(bounty_id, &bounty); // Poke deposit should fail due to invalid status - assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), Error::::UnexpectedStatus); + assert_noop!( + Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), + Error::::UnexpectedStatus + ); // Change status to funded bounty.status = BountyStatus::Funded; pallet_bounties::Bounties::::insert(bounty_id, &bounty); // Poke deposit should fail due to invalid status - assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), Error::::UnexpectedStatus); + assert_noop!( + Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), + Error::::UnexpectedStatus + ); // Change status to curator proposed bounty.status = BountyStatus::CuratorProposed { curator }; pallet_bounties::Bounties::::insert(bounty_id, &bounty); // Poke deposit should fail due to invalid status - assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), Error::::UnexpectedStatus); + assert_noop!( + Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), + Error::::UnexpectedStatus + ); // Change status to active bounty.status = BountyStatus::Active { curator, update_due: 24 }; pallet_bounties::Bounties::::insert(bounty_id, &bounty); // Poke deposit should fail due to invalid status - assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), Error::::UnexpectedStatus); + assert_noop!( + Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), + Error::::UnexpectedStatus + ); // Change status to PendingPayout bounty.status = BountyStatus::PendingPayout { curator, beneficiary: 0, unlock_at: 24 }; pallet_bounties::Bounties::::insert(bounty_id, &bounty); // Poke deposit should fail due to invalid status - assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), Error::::UnexpectedStatus); + assert_noop!( + Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), + Error::::UnexpectedStatus + ); // Change status to ApprovedWithCurator bounty.status = BountyStatus::ApprovedWithCurator { curator }; pallet_bounties::Bounties::::insert(bounty_id, &bounty); // Poke deposit should fail due to invalid status - assert_noop!(Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), Error::::UnexpectedStatus); + assert_noop!( + Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id), + Error::::UnexpectedStatus + ); }); } @@ -1650,27 +1666,25 @@ fn poke_deposit_works_and_charges_fee_for_unchanged_deposit() { let proposer = 0; let deposit = 85; let bounty = Bounty { - proposer: proposer, + proposer, value: 50, fee: 0, curator_deposit: 0, bond: deposit, status: BountyStatus::Proposed, }; - assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(proposer), 50, b"12345".to_vec())); + assert_ok!(Bounties::propose_bounty( + RuntimeOrigin::signed(proposer), + 50, + b"12345".to_vec() + )); // Verify initial state assert_eq!(Balances::reserved_balance(proposer), deposit); assert_eq!(Balances::free_balance(proposer), 100 - deposit); assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); - assert_eq!( - pallet_bounties::Bounties::::get(0).unwrap(), - bounty - ); - assert_eq!( - pallet_bounties::BountyDescriptions::::get(0).unwrap(), - b"12345".to_vec() - ); + assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); assert_eq!(pallet_bounties::BountyCount::::get(), 1); // Poke deposit should charge fee @@ -1680,14 +1694,8 @@ fn poke_deposit_works_and_charges_fee_for_unchanged_deposit() { // Verify final state assert_eq!(Balances::reserved_balance(proposer), deposit); - assert_eq!( - pallet_bounties::Bounties::::get(0).unwrap(), - bounty - ); - assert_eq!( - pallet_bounties::BountyDescriptions::::get(0).unwrap(), - b"12345".to_vec() - ); + assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); assert_eq!(pallet_bounties::BountyCount::::get(), 1); assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); }); @@ -1700,27 +1708,25 @@ fn poke_deposit_works_for_deposit_increase() { let proposer = 0; let deposit = 85; let mut bounty = Bounty { - proposer: proposer, + proposer, value: 50, fee: 0, curator_deposit: 0, bond: deposit, status: BountyStatus::Proposed, }; - assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(proposer), 50, b"12345".to_vec())); + assert_ok!(Bounties::propose_bounty( + RuntimeOrigin::signed(proposer), + 50, + b"12345".to_vec() + )); // Verify initial state assert_eq!(Balances::reserved_balance(proposer), deposit); assert_eq!(Balances::free_balance(proposer), 100 - deposit); assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); - assert_eq!( - pallet_bounties::Bounties::::get(0).unwrap(), - bounty - ); - assert_eq!( - pallet_bounties::BountyDescriptions::::get(0).unwrap(), - b"12345".to_vec() - ); + assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); assert_eq!(pallet_bounties::BountyCount::::get(), 1); // Increase the DataDepositPerByte @@ -1736,16 +1742,13 @@ fn poke_deposit_works_for_deposit_increase() { // Verify final state assert_eq!(Balances::reserved_balance(proposer), new_deposit); assert_eq!(Balances::free_balance(proposer), 100 - new_deposit); - assert_eq!(last_event(), BountiesEvent::DepositPoked { bounty_id, proposer, old_deposit: deposit, new_deposit }); - bounty.bond = new_deposit; assert_eq!( - pallet_bounties::Bounties::::get(0).unwrap(), - bounty - ); - assert_eq!( - pallet_bounties::BountyDescriptions::::get(0).unwrap(), - b"12345".to_vec() + last_event(), + BountiesEvent::DepositPoked { bounty_id, proposer, old_deposit: deposit, new_deposit } ); + bounty.bond = new_deposit; + assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); assert_eq!(pallet_bounties::BountyCount::::get(), 1); }); } @@ -1757,7 +1760,7 @@ fn poke_deposit_works_for_deposit_decrease() { let proposer = 0; let deposit = 90; let mut bounty = Bounty { - proposer: proposer, + proposer, value: 50, fee: 0, curator_deposit: 0, @@ -1765,20 +1768,18 @@ fn poke_deposit_works_for_deposit_decrease() { status: BountyStatus::Proposed, }; DataDepositPerByte::set(2); - assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(proposer), 50, b"12345".to_vec())); + assert_ok!(Bounties::propose_bounty( + RuntimeOrigin::signed(proposer), + 50, + b"12345".to_vec() + )); // Verify initial state assert_eq!(Balances::reserved_balance(proposer), deposit); assert_eq!(Balances::free_balance(proposer), 100 - deposit); assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); - assert_eq!( - pallet_bounties::Bounties::::get(0).unwrap(), - bounty - ); - assert_eq!( - pallet_bounties::BountyDescriptions::::get(0).unwrap(), - b"12345".to_vec() - ); + assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); assert_eq!(pallet_bounties::BountyCount::::get(), 1); // Decrease the DataDepositPerByte @@ -1794,16 +1795,13 @@ fn poke_deposit_works_for_deposit_decrease() { // Verify final state assert_eq!(Balances::reserved_balance(proposer), new_deposit); assert_eq!(Balances::free_balance(proposer), 100 - new_deposit); - assert_eq!(last_event(), BountiesEvent::DepositPoked { bounty_id, proposer, old_deposit: deposit, new_deposit }); - bounty.bond = new_deposit; - assert_eq!( - pallet_bounties::Bounties::::get(0).unwrap(), - bounty - ); assert_eq!( - pallet_bounties::BountyDescriptions::::get(0).unwrap(), - b"12345".to_vec() + last_event(), + BountiesEvent::DepositPoked { bounty_id, proposer, old_deposit: deposit, new_deposit } ); + bounty.bond = new_deposit; + assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); assert_eq!(pallet_bounties::BountyCount::::get(), 1); }); } From caee6a07cadc1888f4c29e51036ba8762cf715a6 Mon Sep 17 00:00:00 2001 From: UtkarshBhardwaj007 Date: Wed, 30 Apr 2025 12:14:28 +0100 Subject: [PATCH 4/9] add prdoc --- prdoc/pr_8382.prdoc | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/prdoc/pr_8382.prdoc b/prdoc/pr_8382.prdoc index 3aad292fdb6ac..a0941c6c6d2b0 100644 --- a/prdoc/pr_8382.prdoc +++ b/prdoc/pr_8382.prdoc @@ -1,24 +1,7 @@ title: add poke_deposit extrinsic to pallet-bounties doc: -- audience: Todo - description: |- - # Description - - * This PR adds a new extrinsic `poke_deposit` to `pallet-bounties`. This extrinsic will be used to re-adjust the deposits made in the pallet to create a new bounty. - * Part of #5591 - - ## Review Notes - - * Added a new extrinsic `poke_deposit` in `pallet-bounties`. - * This extrinsic checks and adjusts the deposits made for creating a bounty. - * Added a new event `DepositPoked` to be emitted upon a successful call of the extrinsic. - * Although the immediate use of the extrinsic will be to give back some of the deposit after the AH-migration, the extrinsic is written such that it can work if the deposit decreases or increases (both). - * The call to the extrinsic would be `free` if an actual adjustment is made to the deposit and `paid` otherwise (when no deposit is changed). - * Added tests to test all scenarios. - * Added benchmarks - - ## TO-DOs - * [ ] Run CI cmd bot to benchmark +- audience: Runtime Dev + description: This PR adds a new extrinsic `poke_deposit` to `pallet-bounties`. This extrinsic will be used to re-adjust the deposits made in the pallet to create a new bounty. crates: - name: rococo-runtime bump: major From da4dbf112c386d17783bff315347fd98f10158c4 Mon Sep 17 00:00:00 2001 From: "cmd[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 13:09:06 +0000 Subject: [PATCH 5/9] Update from github-actions[bot] running command 'bench --pallet pallet_bounties' --- .../rococo/src/weights/pallet_bounties.rs | 78 ++++--- substrate/frame/bounties/src/weights.rs | 199 ++++++++++-------- 2 files changed, 153 insertions(+), 124 deletions(-) diff --git a/polkadot/runtime/rococo/src/weights/pallet_bounties.rs b/polkadot/runtime/rococo/src/weights/pallet_bounties.rs index 6c9902ea832d3..141b9626f5152 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_bounties.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_bounties.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_bounties` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-02-22, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-04-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `d3a9aad6f7a3`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `b5f9d80cc353`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 // Executed Command: @@ -64,11 +64,11 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `210` // Estimated: `3593` - // Minimum execution time: 27_405_000 picoseconds. - Weight::from_parts(28_960_668, 0) + // Minimum execution time: 26_840_000 picoseconds. + Weight::from_parts(28_494_084, 0) .saturating_add(Weight::from_parts(0, 3593)) - // Standard Error: 6 - .saturating_add(Weight::from_parts(607, 0).saturating_mul(d.into())) + // Standard Error: 5 + .saturating_add(Weight::from_parts(644, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -80,8 +80,8 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `302` // Estimated: `3642` - // Minimum execution time: 14_322_000 picoseconds. - Weight::from_parts(14_993_000, 0) + // Minimum execution time: 14_096_000 picoseconds. + Weight::from_parts(14_743_000, 0) .saturating_add(Weight::from_parts(0, 3642)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -92,8 +92,8 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `322` // Estimated: `3642` - // Minimum execution time: 14_227_000 picoseconds. - Weight::from_parts(14_967_000, 0) + // Minimum execution time: 13_949_000 picoseconds. + Weight::from_parts(14_522_000, 0) .saturating_add(Weight::from_parts(0, 3642)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -106,8 +106,8 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `302` // Estimated: `3642` - // Minimum execution time: 16_980_000 picoseconds. - Weight::from_parts(18_167_000, 0) + // Minimum execution time: 17_266_000 picoseconds. + Weight::from_parts(17_968_000, 0) .saturating_add(Weight::from_parts(0, 3642)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -120,8 +120,8 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `498` // Estimated: `3642` - // Minimum execution time: 41_196_000 picoseconds. - Weight::from_parts(42_588_000, 0) + // Minimum execution time: 41_346_000 picoseconds. + Weight::from_parts(42_379_000, 0) .saturating_add(Weight::from_parts(0, 3642)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -134,8 +134,8 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `494` // Estimated: `3642` - // Minimum execution time: 31_821_000 picoseconds. - Weight::from_parts(32_823_000, 0) + // Minimum execution time: 31_182_000 picoseconds. + Weight::from_parts(32_520_000, 0) .saturating_add(Weight::from_parts(0, 3642)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -148,8 +148,8 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `400` // Estimated: `3642` - // Minimum execution time: 18_795_000 picoseconds. - Weight::from_parts(19_758_000, 0) + // Minimum execution time: 17_660_000 picoseconds. + Weight::from_parts(18_922_000, 0) .saturating_add(Weight::from_parts(0, 3642)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -170,8 +170,8 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `764` // Estimated: `8799` - // Minimum execution time: 116_017_000 picoseconds. - Weight::from_parts(117_965_000, 0) + // Minimum execution time: 114_245_000 picoseconds. + Weight::from_parts(119_907_000, 0) .saturating_add(Weight::from_parts(0, 8799)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(8)) @@ -188,8 +188,8 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `444` // Estimated: `3642` - // Minimum execution time: 42_519_000 picoseconds. - Weight::from_parts(44_526_000, 0) + // Minimum execution time: 43_088_000 picoseconds. + Weight::from_parts(44_290_000, 0) .saturating_add(Weight::from_parts(0, 3642)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -208,8 +208,8 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `680` // Estimated: `6196` - // Minimum execution time: 80_800_000 picoseconds. - Weight::from_parts(82_838_000, 0) + // Minimum execution time: 81_575_000 picoseconds. + Weight::from_parts(82_919_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(6)) @@ -220,8 +220,8 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `358` // Estimated: `3642` - // Minimum execution time: 14_685_000 picoseconds. - Weight::from_parts(15_756_000, 0) + // Minimum execution time: 14_680_000 picoseconds. + Weight::from_parts(15_096_000, 0) .saturating_add(Weight::from_parts(0, 3642)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -237,21 +237,31 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + b * (297 ±0)` // Estimated: `1887 + b * (5206 ±0)` - // Minimum execution time: 3_160_000 picoseconds. - Weight::from_parts(3_311_000, 0) + // Minimum execution time: 3_023_000 picoseconds. + Weight::from_parts(3_260_000, 0) .saturating_add(Weight::from_parts(0, 1887)) - // Standard Error: 13_041 - .saturating_add(Weight::from_parts(37_231_411, 0).saturating_mul(b.into())) + // Standard Error: 8_928 + .saturating_add(Weight::from_parts(36_833_581, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(b.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(b.into()))) .saturating_add(Weight::from_parts(0, 5206).saturating_mul(b.into())) } + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:1 w:0) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(16400), added: 18875, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn poke_deposit() -> Weight { - Weight::from_parts(15_756_000, 0) - .saturating_add(Weight::from_parts(0, 3642)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) + // Proof Size summary in bytes: + // Measured: `16795` + // Estimated: `19865` + // Minimum execution time: 38_100_000 picoseconds. + Weight::from_parts(39_566_000, 0) + .saturating_add(Weight::from_parts(0, 19865)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/substrate/frame/bounties/src/weights.rs b/substrate/frame/bounties/src/weights.rs index a4476232a509b..e8777490cf062 100644 --- a/substrate/frame/bounties/src/weights.rs +++ b/substrate/frame/bounties/src/weights.rs @@ -35,9 +35,9 @@ //! Autogenerated weights for `pallet_bounties` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-02-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-04-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `4563561839a5`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `b5f9d80cc353`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` // Executed Command: @@ -58,8 +58,7 @@ // --no-storage-info // --no-min-squares // --no-median-slopes -// --genesis-builder-policy=none -// --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic,pallet_nomination_pools,pallet_remark,pallet_transaction_storage,pallet_election_provider_multi_block,pallet_election_provider_multi_block::signed,pallet_election_provider_multi_block::unsigned,pallet_election_provider_multi_block::verifier +// --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic,pallet_nomination_pools,pallet_remark,pallet_transaction_storage #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -101,12 +100,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `d` is `[0, 300]`. fn propose_bounty(d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `51` + // Measured: `342` // Estimated: `3593` - // Minimum execution time: 22_358_000 picoseconds. - Weight::from_parts(23_077_136, 3593) - // Standard Error: 95 - .saturating_add(Weight::from_parts(304, 0).saturating_mul(d.into())) + // Minimum execution time: 26_048_000 picoseconds. + Weight::from_parts(27_397_398, 3593) + // Standard Error: 189 + .saturating_add(Weight::from_parts(1_244, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -116,10 +115,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) fn approve_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `177` + // Measured: `434` // Estimated: `3642` - // Minimum execution time: 12_172_000 picoseconds. - Weight::from_parts(12_752_000, 3642) + // Minimum execution time: 13_955_000 picoseconds. + Weight::from_parts(14_367_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -127,10 +126,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `196` + // Measured: `454` // Estimated: `3642` - // Minimum execution time: 12_867_000 picoseconds. - Weight::from_parts(13_388_000, 3642) + // Minimum execution time: 15_789_000 picoseconds. + Weight::from_parts(16_314_000, 3642) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -140,10 +139,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) fn approve_bounty_with_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `176` + // Measured: `434` // Estimated: `3642` - // Minimum execution time: 14_120_000 picoseconds. - Weight::from_parts(14_539_000, 3642) + // Minimum execution time: 18_509_000 picoseconds. + Weight::from_parts(19_084_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -153,10 +152,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `334` + // Measured: `630` // Estimated: `3642` - // Minimum execution time: 37_561_000 picoseconds. - Weight::from_parts(38_471_000, 3642) + // Minimum execution time: 41_340_000 picoseconds. + Weight::from_parts(42_360_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -166,10 +165,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `330` + // Measured: `626` // Estimated: `3642` - // Minimum execution time: 28_085_000 picoseconds. - Weight::from_parts(29_224_000, 3642) + // Minimum execution time: 31_637_000 picoseconds. + Weight::from_parts(32_719_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -179,10 +178,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) fn award_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `232` + // Measured: `638` // Estimated: `3642` - // Minimum execution time: 14_694_000 picoseconds. - Weight::from_parts(15_430_000, 3642) + // Minimum execution time: 20_654_000 picoseconds. + Weight::from_parts(21_297_000, 3642) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -200,10 +199,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) fn claim_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `469` + // Measured: `1036` // Estimated: `8799` - // Minimum execution time: 106_782_000 picoseconds. - Weight::from_parts(109_479_000, 8799) + // Minimum execution time: 113_370_000 picoseconds. + Weight::from_parts(115_652_000, 8799) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } @@ -217,10 +216,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn close_bounty_proposed() -> Weight { // Proof Size summary in bytes: - // Measured: `227` + // Measured: `682` // Estimated: `3642` - // Minimum execution time: 36_755_000 picoseconds. - Weight::from_parts(37_464_000, 3642) + // Minimum execution time: 44_456_000 picoseconds. + Weight::from_parts(45_490_000, 3642) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -236,10 +235,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `ChildBounties::ParentTotalChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) fn close_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `437` + // Measured: `952` // Estimated: `6196` - // Minimum execution time: 74_374_000 picoseconds. - Weight::from_parts(75_148_000, 6196) + // Minimum execution time: 80_493_000 picoseconds. + Weight::from_parts(82_826_000, 6196) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -247,10 +246,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) fn extend_bounty_expiry() -> Weight { // Proof Size summary in bytes: - // Measured: `232` + // Measured: `490` // Estimated: `3642` - // Minimum execution time: 13_524_000 picoseconds. - Weight::from_parts(13_905_000, 3642) + // Minimum execution time: 16_142_000 picoseconds. + Weight::from_parts(17_033_000, 3642) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -263,22 +262,32 @@ impl WeightInfo for SubstrateWeight { /// The range of component `b` is `[0, 100]`. fn spend_funds(b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0 + b * (293 ±0)` + // Measured: `71 + b * (298 ±0)` // Estimated: `1887 + b * (5206 ±0)` - // Minimum execution time: 1_076_000 picoseconds. - Weight::from_parts(1_160_000, 1887) - // Standard Error: 8_955 - .saturating_add(Weight::from_parts(35_597_841, 0).saturating_mul(b.into())) + // Minimum execution time: 3_407_000 picoseconds. + Weight::from_parts(3_479_000, 1887) + // Standard Error: 7_458 + .saturating_add(Weight::from_parts(34_548_145, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(b.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(b.into()))) .saturating_add(Weight::from_parts(0, 5206).saturating_mul(b.into())) } + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:1 w:0) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn poke_deposit() -> Weight { - Weight::from_parts(13_905_000, 3642) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Proof Size summary in bytes: + // Measured: `839` + // Estimated: `3779` + // Minimum execution time: 32_478_000 picoseconds. + Weight::from_parts(34_043_000, 3779) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } } @@ -295,12 +304,12 @@ impl WeightInfo for () { /// The range of component `d` is `[0, 300]`. fn propose_bounty(d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `51` + // Measured: `342` // Estimated: `3593` - // Minimum execution time: 22_358_000 picoseconds. - Weight::from_parts(23_077_136, 3593) - // Standard Error: 95 - .saturating_add(Weight::from_parts(304, 0).saturating_mul(d.into())) + // Minimum execution time: 26_048_000 picoseconds. + Weight::from_parts(27_397_398, 3593) + // Standard Error: 189 + .saturating_add(Weight::from_parts(1_244, 0).saturating_mul(d.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -310,10 +319,10 @@ impl WeightInfo for () { /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) fn approve_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `177` + // Measured: `434` // Estimated: `3642` - // Minimum execution time: 12_172_000 picoseconds. - Weight::from_parts(12_752_000, 3642) + // Minimum execution time: 13_955_000 picoseconds. + Weight::from_parts(14_367_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -321,10 +330,10 @@ impl WeightInfo for () { /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) fn propose_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `196` + // Measured: `454` // Estimated: `3642` - // Minimum execution time: 12_867_000 picoseconds. - Weight::from_parts(13_388_000, 3642) + // Minimum execution time: 15_789_000 picoseconds. + Weight::from_parts(16_314_000, 3642) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -334,10 +343,10 @@ impl WeightInfo for () { /// Proof: `Bounties::BountyApprovals` (`max_values`: Some(1), `max_size`: Some(402), added: 897, mode: `MaxEncodedLen`) fn approve_bounty_with_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `176` + // Measured: `434` // Estimated: `3642` - // Minimum execution time: 14_120_000 picoseconds. - Weight::from_parts(14_539_000, 3642) + // Minimum execution time: 18_509_000 picoseconds. + Weight::from_parts(19_084_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -347,10 +356,10 @@ impl WeightInfo for () { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn unassign_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `334` + // Measured: `630` // Estimated: `3642` - // Minimum execution time: 37_561_000 picoseconds. - Weight::from_parts(38_471_000, 3642) + // Minimum execution time: 41_340_000 picoseconds. + Weight::from_parts(42_360_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -360,10 +369,10 @@ impl WeightInfo for () { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn accept_curator() -> Weight { // Proof Size summary in bytes: - // Measured: `330` + // Measured: `626` // Estimated: `3642` - // Minimum execution time: 28_085_000 picoseconds. - Weight::from_parts(29_224_000, 3642) + // Minimum execution time: 31_637_000 picoseconds. + Weight::from_parts(32_719_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -373,10 +382,10 @@ impl WeightInfo for () { /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) fn award_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `232` + // Measured: `638` // Estimated: `3642` - // Minimum execution time: 14_694_000 picoseconds. - Weight::from_parts(15_430_000, 3642) + // Minimum execution time: 20_654_000 picoseconds. + Weight::from_parts(21_297_000, 3642) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -394,10 +403,10 @@ impl WeightInfo for () { /// Proof: `ChildBounties::ParentChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) fn claim_bounty() -> Weight { // Proof Size summary in bytes: - // Measured: `469` + // Measured: `1036` // Estimated: `8799` - // Minimum execution time: 106_782_000 picoseconds. - Weight::from_parts(109_479_000, 8799) + // Minimum execution time: 113_370_000 picoseconds. + Weight::from_parts(115_652_000, 8799) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } @@ -411,10 +420,10 @@ impl WeightInfo for () { /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) fn close_bounty_proposed() -> Weight { // Proof Size summary in bytes: - // Measured: `227` + // Measured: `682` // Estimated: `3642` - // Minimum execution time: 36_755_000 picoseconds. - Weight::from_parts(37_464_000, 3642) + // Minimum execution time: 44_456_000 picoseconds. + Weight::from_parts(45_490_000, 3642) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -430,10 +439,10 @@ impl WeightInfo for () { /// Proof: `ChildBounties::ParentTotalChildBounties` (`max_values`: None, `max_size`: Some(16), added: 2491, mode: `MaxEncodedLen`) fn close_bounty_active() -> Weight { // Proof Size summary in bytes: - // Measured: `437` + // Measured: `952` // Estimated: `6196` - // Minimum execution time: 74_374_000 picoseconds. - Weight::from_parts(75_148_000, 6196) + // Minimum execution time: 80_493_000 picoseconds. + Weight::from_parts(82_826_000, 6196) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -441,10 +450,10 @@ impl WeightInfo for () { /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) fn extend_bounty_expiry() -> Weight { // Proof Size summary in bytes: - // Measured: `232` + // Measured: `490` // Estimated: `3642` - // Minimum execution time: 13_524_000 picoseconds. - Weight::from_parts(13_905_000, 3642) + // Minimum execution time: 16_142_000 picoseconds. + Weight::from_parts(17_033_000, 3642) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -457,21 +466,31 @@ impl WeightInfo for () { /// The range of component `b` is `[0, 100]`. fn spend_funds(b: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `0 + b * (293 ±0)` + // Measured: `71 + b * (298 ±0)` // Estimated: `1887 + b * (5206 ±0)` - // Minimum execution time: 1_076_000 picoseconds. - Weight::from_parts(1_160_000, 1887) - // Standard Error: 8_955 - .saturating_add(Weight::from_parts(35_597_841, 0).saturating_mul(b.into())) + // Minimum execution time: 3_407_000 picoseconds. + Weight::from_parts(3_479_000, 1887) + // Standard Error: 7_458 + .saturating_add(Weight::from_parts(34_548_145, 0).saturating_mul(b.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(b.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(b.into()))) .saturating_add(Weight::from_parts(0, 5206).saturating_mul(b.into())) } + /// Storage: `Bounties::Bounties` (r:1 w:1) + /// Proof: `Bounties::Bounties` (`max_values`: None, `max_size`: Some(177), added: 2652, mode: `MaxEncodedLen`) + /// Storage: `Bounties::BountyDescriptions` (r:1 w:0) + /// Proof: `Bounties::BountyDescriptions` (`max_values`: None, `max_size`: Some(314), added: 2789, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn poke_deposit() -> Weight { - Weight::from_parts(13_905_000, 3642) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Proof Size summary in bytes: + // Measured: `839` + // Estimated: `3779` + // Minimum execution time: 32_478_000 picoseconds. + Weight::from_parts(34_043_000, 3779) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } } From a6f2f2b0928ca588f2669306cdfe03e39819af04 Mon Sep 17 00:00:00 2001 From: UtkarshBhardwaj007 Date: Sun, 11 May 2025 01:45:38 +0100 Subject: [PATCH 6/9] allow anyone to poke deposits --- substrate/frame/bounties/src/benchmarking.rs | 8 +- substrate/frame/bounties/src/lib.rs | 19 +-- substrate/frame/bounties/src/tests.rs | 143 ++++++++++++------- 3 files changed, 98 insertions(+), 72 deletions(-) diff --git a/substrate/frame/bounties/src/benchmarking.rs b/substrate/frame/bounties/src/benchmarking.rs index 18003e5c6ea56..cd410e89d51b4 100644 --- a/substrate/frame/bounties/src/benchmarking.rs +++ b/substrate/frame/bounties/src/benchmarking.rs @@ -279,13 +279,11 @@ benchmarks_instance_pallet! { let old_deposit = T::Currency::reserved_balance(&caller); // Modify the description to be maximum length let max_description: Vec = vec![0; T::MaximumReasonLength::get() as usize]; - let bounded_description: BoundedVec = max_description.try_into() - .expect("description length was set to T::MaximumReasonLength; qed"); - BountyDescriptions::::insert(bounty_id, bounded_description); + let bounded_description: BoundedVec = max_description.try_into().unwrap(); + BountyDescriptions::::insert(bounty_id, &bounded_description); // Ensure caller has enough balance for new deposit - let new_deposit = T::BountyDepositBase::get() - .saturating_add(T::DataDepositPerByte::get().saturating_mul((T::MaximumReasonLength::get()).into())); + let new_deposit = Bounties::::calculate_bounty_deposit(&bounded_description); let required_balance = new_deposit.saturating_add(minimum_balance::()); T::Currency::make_free_balance_be(&caller, required_balance); diff --git a/substrate/frame/bounties/src/lib.rs b/substrate/frame/bounties/src/lib.rs index 397f845749452..a03e9dbf8194b 100644 --- a/substrate/frame/bounties/src/lib.rs +++ b/substrate/frame/bounties/src/lib.rs @@ -897,10 +897,9 @@ pub mod pallet { /// Poke the deposit reserved for creating a bounty proposal. /// - /// This can be used by accounts to possibly lower their locked amount. + /// This can be used by accounts to update their reserved amount. /// - /// The dispatch origin for this call must be _Signed_ and must be the proposer of the - /// bounty. + /// The dispatch origin for this call must be _Signed_. /// /// Parameters: /// - `bounty_id`: The bounty id for which to adjust the deposit. @@ -917,9 +916,9 @@ pub mod pallet { origin: OriginFor, #[pallet::compact] bounty_id: BountyIndex, ) -> DispatchResultWithPostInfo { - let who = ensure_signed(origin)?; + ensure_signed(origin)?; - let deposit_updated = Self::poke_bounty_deposit(bounty_id, who)?; + let deposit_updated = Self::poke_bounty_deposit(bounty_id)?; Ok(if deposit_updated { Pays::No } else { Pays::Yes }.into()) } @@ -1060,7 +1059,6 @@ impl, I: 'static> Pallet { /// Returns true if the deposit was updated and false otherwise. fn poke_bounty_deposit( bounty_id: BountyIndex, - who: T::AccountId, ) -> Result { let mut bounty = Bounties::::get(bounty_id).ok_or(Error::::InvalidIndex)?; let bounty_description = @@ -1068,9 +1066,6 @@ impl, I: 'static> Pallet { // ensure that the bounty status is proposed. ensure!(bounty.status == BountyStatus::Proposed, Error::::UnexpectedStatus); - // ensure that bounty proposer is the origin for this call. - ensure!(bounty.proposer == who, Error::::NotProposer); - let new_bond = Self::calculate_bounty_deposit(&bounty_description); let old_bond = bounty.bond; if new_bond == old_bond { @@ -1078,10 +1073,10 @@ impl, I: 'static> Pallet { } if new_bond > old_bond { let extra = new_bond.saturating_sub(old_bond); - T::Currency::reserve(&who, extra)?; + T::Currency::reserve(&bounty.proposer, extra)?; } else { let excess = old_bond.saturating_sub(new_bond); - let remaining_unreserved = T::Currency::unreserve(&who, excess); + let remaining_unreserved = T::Currency::unreserve(&bounty.proposer, excess); if !remaining_unreserved.is_zero() { defensive!( "Failed to unreserve full amount. (Requested, Actual)", @@ -1094,7 +1089,7 @@ impl, I: 'static> Pallet { Self::deposit_event(Event::::DepositPoked { bounty_id, - proposer: who, + proposer: bounty.proposer, old_deposit: old_bond, new_deposit: new_bond, }); diff --git a/substrate/frame/bounties/src/tests.rs b/substrate/frame/bounties/src/tests.rs index 7220a2ebd56e1..a7dff7f8f0217 100644 --- a/substrate/frame/bounties/src/tests.rs +++ b/substrate/frame/bounties/src/tests.rs @@ -1486,11 +1486,14 @@ fn accept_curator_sets_update_due_correctly() { #[test] fn poke_deposit_fails_for_insufficient_balance() { ExtBuilder::default().build_and_execute(|| { + // Create a description for the bounty + let description = b"12345".to_vec(); + let bounded_description = description.clone().try_into().unwrap(); // Create a bounty - assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec())); + assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, description.clone())); // BountyDepositBase (80) + DataDepositPerByte (1) * description.len() (5) - let deposit = 85; + let deposit = pallet_bounties::Pallet::::calculate_bounty_deposit(&bounded_description); // Verify initial state assert_eq!(Balances::reserved_balance(0), deposit); @@ -1507,7 +1510,7 @@ fn poke_deposit_fails_for_insufficient_balance() { status: BountyStatus::Proposed, } ); - assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), description); assert_eq!(pallet_bounties::BountyCount::::get(), 1); // Increase the DataDepositPerByte to be more than the total balance of the proposer @@ -1538,41 +1541,6 @@ fn poke_deposit_fails_for_non_existent_bounty() { }); } -#[test] -fn poke_deposit_fails_for_non_proposer() { - ExtBuilder::default().build_and_execute(|| { - assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, b"12345".to_vec())); - - // BountyDepositBase (80) + DataDepositPerByte (1) * description.len() (5) - let deposit = 85; - - // Verify initial state - assert_eq!(Balances::reserved_balance(0), deposit); - assert_eq!(Balances::reserved_balance(1), 0); - assert_eq!(Balances::free_balance(0), 100 - deposit); - assert_eq!(last_event(), BountiesEvent::BountyProposed { index: 0 }); - assert_eq!( - pallet_bounties::Bounties::::get(0).unwrap(), - Bounty { - proposer: 0, - value: 50, - fee: 0, - curator_deposit: 0, - bond: deposit, - status: BountyStatus::Proposed, - } - ); - assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); - assert_eq!(pallet_bounties::BountyCount::::get(), 1); - - // Poke deposit should fail due to non-proposer - assert_noop!( - Bounties::poke_deposit(RuntimeOrigin::signed(1), 0), - Error::::NotProposer - ); - }); -} - #[test] fn poke_deposit_fails_for_any_status_other_than_proposed() { ExtBuilder::default().build_and_execute(|| { @@ -1588,10 +1556,11 @@ fn poke_deposit_fails_for_any_status_other_than_proposed() { bond: deposit, status: BountyStatus::Proposed, }; + let description = b"12345".to_vec(); assert_ok!(Bounties::propose_bounty( RuntimeOrigin::signed(proposer), 50, - b"12345".to_vec() + description.clone() )); // Verify initial state @@ -1600,7 +1569,7 @@ fn poke_deposit_fails_for_any_status_other_than_proposed() { assert_eq!(Balances::free_balance(proposer), 100 - deposit); assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); - assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), description); assert_eq!(pallet_bounties::BountyCount::::get(), 1); // Change status to approved @@ -1664,7 +1633,9 @@ fn poke_deposit_works_and_charges_fee_for_unchanged_deposit() { ExtBuilder::default().build_and_execute(|| { let bounty_id = 0; let proposer = 0; - let deposit = 85; + let description = b"12345".to_vec(); + let bounded_description = description.clone().try_into().unwrap(); + let deposit = Bounties::calculate_bounty_deposit(&bounded_description); let bounty = Bounty { proposer, value: 50, @@ -1676,7 +1647,7 @@ fn poke_deposit_works_and_charges_fee_for_unchanged_deposit() { assert_ok!(Bounties::propose_bounty( RuntimeOrigin::signed(proposer), 50, - b"12345".to_vec() + description.clone() )); // Verify initial state @@ -1684,7 +1655,7 @@ fn poke_deposit_works_and_charges_fee_for_unchanged_deposit() { assert_eq!(Balances::free_balance(proposer), 100 - deposit); assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); - assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), description); assert_eq!(pallet_bounties::BountyCount::::get(), 1); // Poke deposit should charge fee @@ -1695,7 +1666,7 @@ fn poke_deposit_works_and_charges_fee_for_unchanged_deposit() { // Verify final state assert_eq!(Balances::reserved_balance(proposer), deposit); assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); - assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), description); assert_eq!(pallet_bounties::BountyCount::::get(), 1); assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); }); @@ -1706,7 +1677,9 @@ fn poke_deposit_works_for_deposit_increase() { ExtBuilder::default().build_and_execute(|| { let bounty_id = 0; let proposer = 0; - let deposit = 85; + let description = b"12345".to_vec(); + let bounded_description = description.clone().try_into().unwrap(); + let deposit = Bounties::calculate_bounty_deposit(&bounded_description); let mut bounty = Bounty { proposer, value: 50, @@ -1718,7 +1691,7 @@ fn poke_deposit_works_for_deposit_increase() { assert_ok!(Bounties::propose_bounty( RuntimeOrigin::signed(proposer), 50, - b"12345".to_vec() + description.clone() )); // Verify initial state @@ -1726,13 +1699,13 @@ fn poke_deposit_works_for_deposit_increase() { assert_eq!(Balances::free_balance(proposer), 100 - deposit); assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); - assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), description); assert_eq!(pallet_bounties::BountyCount::::get(), 1); // Increase the DataDepositPerByte DataDepositPerByte::set(2); // BountyDepositBase (80) + DataDepositPerByte (2) * description.len() (5) - let new_deposit = 90; + let new_deposit = Bounties::calculate_bounty_deposit(&bounded_description); // Poke deposit should increase reserve let result = Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id); @@ -1748,7 +1721,7 @@ fn poke_deposit_works_for_deposit_increase() { ); bounty.bond = new_deposit; assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); - assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), description); assert_eq!(pallet_bounties::BountyCount::::get(), 1); }); } @@ -1758,7 +1731,10 @@ fn poke_deposit_works_for_deposit_decrease() { ExtBuilder::default().build_and_execute(|| { let bounty_id = 0; let proposer = 0; - let deposit = 90; + let description = b"12345".to_vec(); + let bounded_description = description.clone().try_into().unwrap(); + DataDepositPerByte::set(2); + let deposit = Bounties::calculate_bounty_deposit(&bounded_description); let mut bounty = Bounty { proposer, value: 50, @@ -1767,11 +1743,11 @@ fn poke_deposit_works_for_deposit_decrease() { bond: deposit, status: BountyStatus::Proposed, }; - DataDepositPerByte::set(2); + assert_ok!(Bounties::propose_bounty( RuntimeOrigin::signed(proposer), 50, - b"12345".to_vec() + description.clone() )); // Verify initial state @@ -1779,13 +1755,13 @@ fn poke_deposit_works_for_deposit_decrease() { assert_eq!(Balances::free_balance(proposer), 100 - deposit); assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); - assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), description); assert_eq!(pallet_bounties::BountyCount::::get(), 1); // Decrease the DataDepositPerByte DataDepositPerByte::set(1); // BountyDepositBase (80) + DataDepositPerByte (2) * description.len() (5) - let new_deposit = 85; + let new_deposit = Bounties::calculate_bounty_deposit(&bounded_description); // Poke deposit should increase reserve let result = Bounties::poke_deposit(RuntimeOrigin::signed(proposer), bounty_id); @@ -1801,7 +1777,64 @@ fn poke_deposit_works_for_deposit_decrease() { ); bounty.bond = new_deposit; assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); - assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), b"12345".to_vec()); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), description); + assert_eq!(pallet_bounties::BountyCount::::get(), 1); + }); +} + +#[test] +fn poke_deposit_works_for_non_proposer() { + ExtBuilder::default().build_and_execute(|| { + let bounty_id = 0; + let proposer = 0; + let non_proposer = 1; + let description = b"12345".to_vec(); + let bounded_description = description.clone().try_into().unwrap(); + + DataDepositPerByte::set(2); + let deposit = Bounties::calculate_bounty_deposit(&bounded_description); + let mut bounty = Bounty { + proposer, + value: 50, + fee: 0, + curator_deposit: 0, + bond: deposit, + status: BountyStatus::Proposed, + }; + assert_ok!(Bounties::propose_bounty( + RuntimeOrigin::signed(proposer), + 50, + description.clone() + )); + + // Verify initial state + assert_eq!(Balances::reserved_balance(proposer), deposit); + assert_eq!(Balances::free_balance(proposer), 100 - deposit); + assert_eq!(last_event(), BountiesEvent::BountyProposed { index: bounty_id }); + assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), description); + assert_eq!(pallet_bounties::BountyCount::::get(), 1); + + // Decrease the DataDepositPerByte + DataDepositPerByte::set(1); + // BountyDepositBase (80) + DataDepositPerByte (2) * description.len() (5) + let new_deposit = Bounties::calculate_bounty_deposit(&bounded_description); + + // Poke deposit should increase reserve + let result = Bounties::poke_deposit(RuntimeOrigin::signed(non_proposer), bounty_id); + assert_ok!(result.as_ref()); + assert_eq!(result.unwrap(), Pays::No.into()); + + // Verify final state + assert_eq!(Balances::reserved_balance(proposer), new_deposit); + assert_eq!(Balances::free_balance(proposer), 100 - new_deposit); + assert_eq!( + last_event(), + BountiesEvent::DepositPoked { bounty_id, proposer, old_deposit: deposit, new_deposit } + ); + bounty.bond = new_deposit; + assert_eq!(pallet_bounties::Bounties::::get(0).unwrap(), bounty); + assert_eq!(pallet_bounties::BountyDescriptions::::get(0).unwrap(), description); assert_eq!(pallet_bounties::BountyCount::::get(), 1); }); } From 944c28cf3ae2db938db431e07a8554a7db79a8e3 Mon Sep 17 00:00:00 2001 From: "cmd[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 11 May 2025 00:49:03 +0000 Subject: [PATCH 7/9] Update from github-actions[bot] running command 'fmt' --- substrate/frame/bounties/src/lib.rs | 4 +--- substrate/frame/bounties/src/tests.rs | 7 ++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/substrate/frame/bounties/src/lib.rs b/substrate/frame/bounties/src/lib.rs index a03e9dbf8194b..05e4c94babec8 100644 --- a/substrate/frame/bounties/src/lib.rs +++ b/substrate/frame/bounties/src/lib.rs @@ -1057,9 +1057,7 @@ impl, I: 'static> Pallet { /// Helper function to poke the deposit reserved for proposing a bounty. /// /// Returns true if the deposit was updated and false otherwise. - fn poke_bounty_deposit( - bounty_id: BountyIndex, - ) -> Result { + fn poke_bounty_deposit(bounty_id: BountyIndex) -> Result { let mut bounty = Bounties::::get(bounty_id).ok_or(Error::::InvalidIndex)?; let bounty_description = BountyDescriptions::::get(bounty_id).ok_or(Error::::InvalidIndex)?; diff --git a/substrate/frame/bounties/src/tests.rs b/substrate/frame/bounties/src/tests.rs index a7dff7f8f0217..ed6b60869135c 100644 --- a/substrate/frame/bounties/src/tests.rs +++ b/substrate/frame/bounties/src/tests.rs @@ -1493,7 +1493,8 @@ fn poke_deposit_fails_for_insufficient_balance() { assert_ok!(Bounties::propose_bounty(RuntimeOrigin::signed(0), 50, description.clone())); // BountyDepositBase (80) + DataDepositPerByte (1) * description.len() (5) - let deposit = pallet_bounties::Pallet::::calculate_bounty_deposit(&bounded_description); + let deposit = + pallet_bounties::Pallet::::calculate_bounty_deposit(&bounded_description); // Verify initial state assert_eq!(Balances::reserved_balance(0), deposit); @@ -1678,7 +1679,7 @@ fn poke_deposit_works_for_deposit_increase() { let bounty_id = 0; let proposer = 0; let description = b"12345".to_vec(); - let bounded_description = description.clone().try_into().unwrap(); + let bounded_description = description.clone().try_into().unwrap(); let deposit = Bounties::calculate_bounty_deposit(&bounded_description); let mut bounty = Bounty { proposer, @@ -1790,7 +1791,7 @@ fn poke_deposit_works_for_non_proposer() { let non_proposer = 1; let description = b"12345".to_vec(); let bounded_description = description.clone().try_into().unwrap(); - + DataDepositPerByte::set(2); let deposit = Bounties::calculate_bounty_deposit(&bounded_description); let mut bounty = Bounty { From c8c54268da40d74fe4a3db1f6b9108124f95219a Mon Sep 17 00:00:00 2001 From: UtkarshBhardwaj007 Date: Mon, 26 May 2025 16:42:34 +0530 Subject: [PATCH 8/9] use saturating math --- substrate/frame/bounties/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/substrate/frame/bounties/src/lib.rs b/substrate/frame/bounties/src/lib.rs index 05e4c94babec8..233596d217001 100644 --- a/substrate/frame/bounties/src/lib.rs +++ b/substrate/frame/bounties/src/lib.rs @@ -1050,8 +1050,9 @@ impl, I: 'static> Pallet { fn calculate_bounty_deposit( description: &BoundedVec, ) -> BalanceOf { - T::BountyDepositBase::get() + - T::DataDepositPerByte::get() * (description.len() as u32).into() + T::BountyDepositBase::get().saturating_add( + T::DataDepositPerByte::get().saturating_mul((description.len() as u32).into()) + ) } /// Helper function to poke the deposit reserved for proposing a bounty. From 291c1de45dba450602bd8ec18cd2286634280741 Mon Sep 17 00:00:00 2001 From: "cmd[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 26 May 2025 11:16:08 +0000 Subject: [PATCH 9/9] Update from github-actions[bot] running command 'fmt' --- substrate/frame/bounties/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/bounties/src/lib.rs b/substrate/frame/bounties/src/lib.rs index 233596d217001..f170b9960c21b 100644 --- a/substrate/frame/bounties/src/lib.rs +++ b/substrate/frame/bounties/src/lib.rs @@ -1051,7 +1051,7 @@ impl, I: 'static> Pallet { description: &BoundedVec, ) -> BalanceOf { T::BountyDepositBase::get().saturating_add( - T::DataDepositPerByte::get().saturating_mul((description.len() as u32).into()) + T::DataDepositPerByte::get().saturating_mul((description.len() as u32).into()), ) }