From c2cd9ea7463f43f6d9bbd5ac79e89ab943e45280 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 22 Mar 2024 17:44:49 +0700 Subject: [PATCH 001/159] wip staking rewards --- Cargo.lock | 20 ++ Cargo.toml | 1 + substrate/frame/staking-rewards/Cargo.toml | 68 ++++++ substrate/frame/staking-rewards/src/lib.rs | 251 +++++++++++++++++++++ 4 files changed, 340 insertions(+) create mode 100644 substrate/frame/staking-rewards/Cargo.toml create mode 100644 substrate/frame/staking-rewards/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index bdbf6ddac268..451497f7f5c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10869,6 +10869,26 @@ dependencies = [ "sp-arithmetic", ] +[[package]] +name = "pallet-staking-rewards" +version = "1.0.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-assets", + "pallet-balances", + "parity-scale-codec", + "primitive-types", + "scale-info", + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 14.0.0", +] + [[package]] name = "pallet-staking-runtime-api" version = "14.0.0" diff --git a/Cargo.toml b/Cargo.toml index 01d6ef8e87bd..6bcd830f14c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -381,6 +381,7 @@ members = [ "substrate/frame/session/benchmarking", "substrate/frame/society", "substrate/frame/staking", + "substrate/frame/staking-rewards", "substrate/frame/staking/reward-curve", "substrate/frame/staking/reward-fn", "substrate/frame/staking/runtime-api", diff --git a/substrate/frame/staking-rewards/Cargo.toml b/substrate/frame/staking-rewards/Cargo.toml new file mode 100644 index 000000000000..0a693545f764 --- /dev/null +++ b/substrate/frame/staking-rewards/Cargo.toml @@ -0,0 +1,68 @@ +[package] +name = "pallet-staking-rewards" +version = "1.0.0" +authors.workspace = true +edition.workspace = true +license = "Apache-2.0" +homepage = "https://substrate.io" +repository.workspace = true +description = "FRAME staking rewards pallet" +readme = "README.md" + +[lints] +workspace = true + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +frame-support = { path = "../support", default-features = false } +frame-system = { path = "../system", default-features = false } +frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +sp-api = { path = "../../primitives/api", default-features = false } +sp-core = { path = "../../primitives/core", default-features = false } +sp-io = { path = "../../primitives/io", default-features = false } +sp-std = { path = "../../primitives/std", default-features = false } +sp-runtime = { path = "../../primitives/runtime", default-features = false } +sp-arithmetic = { path = "../../primitives/arithmetic", default-features = false } + +[dev-dependencies] +pallet-balances = { path = "../balances" } +pallet-assets = { path = "../assets" } +primitive-types = { version = "0.12.0", default-features = false, features = ["codec", "num-traits", "scale-info"] } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "pallet-assets/std", + "pallet-balances/std", + "primitive-types/std", + "scale-info/std", + "sp-api/std", + "sp-arithmetic/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "pallet-assets/try-runtime", + "pallet-balances/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/substrate/frame/staking-rewards/src/lib.rs b/substrate/frame/staking-rewards/src/lib.rs new file mode 100644 index 000000000000..d100e11cba76 --- /dev/null +++ b/substrate/frame/staking-rewards/src/lib.rs @@ -0,0 +1,251 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # FRAME Staking Rewards Pallet +//! +//! A pallet that allows users to stake assets and receive rewards in return. +//! +//! Based on the [AccumulatedRewardsPerShare](https://dev.to/heymarkkop/understanding-sushiswaps-masterchef-staking-rewards-1m6f) algorithm. +#![deny(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_system::pallet_prelude::BlockNumberFor; +pub use pallet::*; + +use frame_support::{ + traits::{ + fungibles::{Balanced, Inspect, Mutate}, + tokens::Balance, + }, + PalletId, +}; +use scale_info::TypeInfo; +use sp_core::Get; +use sp_runtime::{DispatchError, Saturating}; +use sp_std::boxed::Box; + +/// Unique identifier for a staking pool. (staking_asset, reward_asset). +pub type PoolId = (AssetId, AssetId); + +/// Information on a user currently staking in a pool. +#[derive(Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] +pub struct PoolStakerInfo { + amount: Balance, + rewards: Balance, + reward_debt: Balance, +} + +/// Staking pool. +#[derive(Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] +pub struct PoolInfo { + reward_rate_per_block: Balance, + total_tokens_staked: Balance, + accumulated_rewards_per_share: Balance, + last_rewarded_block: BlockNumber, +} + +#[frame_support::pallet(dev_mode)] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + use sp_runtime::traits::AccountIdConversion; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + /// Overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// The pallet's id, used for deriving its sovereign account ID. + #[pallet::constant] + type PalletId: Get; + + /// Identifier for each type of asset. + type AssetId: Member + Parameter + Clone + MaybeSerializeDeserialize + MaxEncodedLen; + + /// The type in which the assets are measured. + type Balance: Balance + TypeInfo; + + /// Registry of assets that can be configured to either stake for rewards, or be offered as + /// rewards for staking. + type Assets: Inspect + + Mutate + + Balanced; + } + + /// State of stakers in each pool. + #[pallet::storage] + pub type PoolStakers = StorageDoubleMap< + _, + Blake2_128Concat, + PoolId, + Blake2_128Concat, + T::AccountId, + PoolStakerInfo, + >; + + /// State and configuraiton of each staking pool. + #[pallet::storage] + pub type Pools = StorageMap< + _, + Blake2_128Concat, + PoolId, + PoolInfo>, + >; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// An account staked some tokens in a pool. + Stake { + /// The account. + who: T::AccountId, + /// The pool. + pool_id: PoolId, + /// The amount. + amount: T::Balance, + }, + /// An account unstaked some tokens from a pool. + Unstake { + /// The account. + who: T::AccountId, + /// The pool. + pool_id: PoolId, + /// The amount. + amount: T::Balance, + }, + /// An account harvested some rewards. + RewardsHarvested { + /// The account. + who: T::AccountId, + /// The pool. + pool_id: PoolId, + /// The rewarded tokens. + amount: T::Balance, + }, + /// A new reward pool was created. + PoolCreated { + /// The pool. + pool_id: PoolId, + /// The initial reward rate per block. + reward_rate_per_block: T::Balance, + }, + /// A reward pool was deleted. + PoolDeleted { + /// The pool. + pool_id: PoolId, + }, + /// A pool reward rate was been changed. + PoolRewardRateChanged { + /// The pool with the changed reward rate. + pool_id: PoolId, + /// The new reward rate of the reward rate per block distributed to stakers. + reward_rate_per_block: T::Balance, + }, + /// Funds were withdrawn from the Reward Pool. + RewardPoolWithdrawal { + /// The asset withdrawn. + reward_asset_id: T::AssetId, + /// The caller. + caller: T::AccountId, + /// The acount of reward asset withdrawn. + amount: T::Balance, + }, + } + + #[pallet::error] + pub enum Error { + /// TODO + TODO, + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn integrity_test() { + todo!() + } + } + + /// Pallet's callable functions. + #[pallet::call] + impl Pallet { + /// Create a new reward pool. + pub fn create_pool( + _origin: OriginFor, + _staked_asset_id: T::AssetId, + _reward_asset_id: T::AssetId, + ) -> DispatchResult { + todo!() + } + + /// Removes an existing reward pool. + /// + /// TODO decide how to manage clean up of stakers from a removed pool + pub fn remove_pool( + _origin: OriginFor, + _staked_asset_id: T::AssetId, + _reward_asset_id: T::AssetId, + ) -> DispatchResult { + todo!() + } + + /// Stake tokens in a pool. + pub fn stake( + _origin: OriginFor, + _staked_asset_id: T::AssetId, + _reward_asset_id: T::AssetId, + _amount: T::Balance, + ) -> DispatchResult { + todo!() + } + + /// Unstake tokens from a pool. + pub fn unstake( + _origin: OriginFor, + _staked_asset_id: T::AssetId, + _reward_asset_id: T::AssetId, + _amount: T::Balance, + ) -> DispatchResult { + todo!() + } + + /// Harvest unclaimed pool rewards. + pub fn harvest_rewards( + _origin: OriginFor, + _staked_asset_id: T::AssetId, + _reward_asset_id: T::AssetId, + ) -> DispatchResult { + todo!() + } + } + + impl Pallet { + /// The account ID of the reward pot. + fn reward_pool_account_id() -> T::AccountId { + T::PalletId::get().into_account_truncating() + } + + /// Update pool state in preparation for reward harvesting. + fn update_pool_rewards(_staked_asset_id: T::AssetId, _reward_asset_id: T::AssetId) { + todo!() + } + } +} From a02d843011c87197464ce7ac24247a3c34fa4dbe Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Mon, 25 Mar 2024 11:45:44 +0700 Subject: [PATCH 002/159] write brief overview --- substrate/frame/staking-rewards/src/lib.rs | 63 ++++++++++++++++------ 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/substrate/frame/staking-rewards/src/lib.rs b/substrate/frame/staking-rewards/src/lib.rs index d100e11cba76..cffa6411b017 100644 --- a/substrate/frame/staking-rewards/src/lib.rs +++ b/substrate/frame/staking-rewards/src/lib.rs @@ -17,9 +17,31 @@ //! # FRAME Staking Rewards Pallet //! -//! A pallet that allows users to stake assets and receive rewards in return. +//! Allows rewarding fungible token holders. //! -//! Based on the [AccumulatedRewardsPerShare](https://dev.to/heymarkkop/understanding-sushiswaps-masterchef-staking-rewards-1m6f) algorithm. +//! ## Overview +//! +//! Governance can create a new incentive program for a fungible asset by creating a new pool. +//! +//! When creating the pool, governance specifies a 'staking asset', 'reward asset', and 'reward rate +//! per block'. +//! +//! Once the pool is created, holders of the 'staking asset' can stake them in this pallet (creating +//! a new Freeze). Once staked, the staker begins accumulating the right to claim the 'reward asset' +//! each block, proportional to their share of the total staked tokens in the pool. +//! +//! Reward assets pending distribution are held in an account derived from the Pallet's ID. +//! This pool should be adequately funded to ensure there are enough funds to make good on staker +//! claims. +//! +//! ## Implementation Notes +//! +//! The implementation is based on the [AccumulatedRewardsPerShare](https://dev.to/heymarkkop/understanding-sushiswaps-masterchef-staking-rewards-1m6f) algorithm. +//! +//! Rewards are calculated JIT (just-in-time), when a staker claims their rewards. +//! +//! All operations are O(1), allowing the approach to scale to an arbitrary amount of pools and +//! stakers. #![deny(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] @@ -43,7 +65,7 @@ use sp_std::boxed::Box; pub type PoolId = (AssetId, AssetId); /// Information on a user currently staking in a pool. -#[derive(Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] +#[derive(Decode, Encode, MaxEncodedLen, TypeInfo)] pub struct PoolStakerInfo { amount: Balance, rewards: Balance, @@ -51,7 +73,7 @@ pub struct PoolStakerInfo { } /// Staking pool. -#[derive(Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] +#[derive(Decode, Encode, MaxEncodedLen, TypeInfo)] pub struct PoolInfo { reward_rate_per_block: Balance, total_tokens_staked: Balance, @@ -115,7 +137,7 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// An account staked some tokens in a pool. - Stake { + Staked { /// The account. who: T::AccountId, /// The pool. @@ -124,7 +146,7 @@ pub mod pallet { amount: T::Balance, }, /// An account unstaked some tokens from a pool. - Unstake { + Unstaked { /// The account. who: T::AccountId, /// The pool. @@ -190,8 +212,8 @@ pub mod pallet { /// Create a new reward pool. pub fn create_pool( _origin: OriginFor, - _staked_asset_id: T::AssetId, - _reward_asset_id: T::AssetId, + _staked_asset_id: Box, + _reward_asset_id: Box, ) -> DispatchResult { todo!() } @@ -201,8 +223,8 @@ pub mod pallet { /// TODO decide how to manage clean up of stakers from a removed pool pub fn remove_pool( _origin: OriginFor, - _staked_asset_id: T::AssetId, - _reward_asset_id: T::AssetId, + _staked_asset_id: Box, + _reward_asset_id: Box, ) -> DispatchResult { todo!() } @@ -210,8 +232,8 @@ pub mod pallet { /// Stake tokens in a pool. pub fn stake( _origin: OriginFor, - _staked_asset_id: T::AssetId, - _reward_asset_id: T::AssetId, + _staked_asset_id: Box, + _reward_asset_id: Box, _amount: T::Balance, ) -> DispatchResult { todo!() @@ -220,8 +242,8 @@ pub mod pallet { /// Unstake tokens from a pool. pub fn unstake( _origin: OriginFor, - _staked_asset_id: T::AssetId, - _reward_asset_id: T::AssetId, + _staked_asset_id: Box, + _reward_asset_id: Box, _amount: T::Balance, ) -> DispatchResult { todo!() @@ -230,8 +252,17 @@ pub mod pallet { /// Harvest unclaimed pool rewards. pub fn harvest_rewards( _origin: OriginFor, - _staked_asset_id: T::AssetId, - _reward_asset_id: T::AssetId, + _staked_asset_id: Box, + _reward_asset_id: Box, + ) -> DispatchResult { + todo!() + } + + /// Modify the reward rate of a pool. + pub fn modify_pool( + _origin: OriginFor, + _staked_asset_id: Box, + _reward_asset_id: Box, ) -> DispatchResult { todo!() } From 0ed5f8d742daec8d9b06baf2ab0fd32c3ed07523 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Mon, 25 Mar 2024 13:59:59 +0700 Subject: [PATCH 003/159] seperate reward pots per pool --- substrate/frame/staking-rewards/src/lib.rs | 176 +++++++++++++-------- 1 file changed, 113 insertions(+), 63 deletions(-) diff --git a/substrate/frame/staking-rewards/src/lib.rs b/substrate/frame/staking-rewards/src/lib.rs index cffa6411b017..4b282bc02059 100644 --- a/substrate/frame/staking-rewards/src/lib.rs +++ b/substrate/frame/staking-rewards/src/lib.rs @@ -30,9 +30,16 @@ //! a new Freeze). Once staked, the staker begins accumulating the right to claim the 'reward asset' //! each block, proportional to their share of the total staked tokens in the pool. //! -//! Reward assets pending distribution are held in an account derived from the Pallet's ID. -//! This pool should be adequately funded to ensure there are enough funds to make good on staker -//! claims. +//! Reward assets pending distribution are held in an account derived from the pallet ID and a +//! unique pool ID. +//! +//! Care should be taken to keep pool accounts adequately funded with the reward asset. +//! +//! ## Permissioning +//! +//! Currently, pool creation and management is permissioned and restricted to a configured Origin. +//! +//! Future iterations of this pallet may allow permissionless creation and management of pools. //! //! ## Implementation Notes //! @@ -61,10 +68,7 @@ use sp_core::Get; use sp_runtime::{DispatchError, Saturating}; use sp_std::boxed::Box; -/// Unique identifier for a staking pool. (staking_asset, reward_asset). -pub type PoolId = (AssetId, AssetId); - -/// Information on a user currently staking in a pool. +/// A pool staker. #[derive(Decode, Encode, MaxEncodedLen, TypeInfo)] pub struct PoolStakerInfo { amount: Balance, @@ -72,19 +76,32 @@ pub struct PoolStakerInfo { reward_debt: Balance, } -/// Staking pool. -#[derive(Decode, Encode, MaxEncodedLen, TypeInfo)] -pub struct PoolInfo { +/// A staking pool. +// #[derive(Decode, Encode, MaxEncodedLen, TypeInfo)] +#[derive(Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] +pub struct PoolInfo { + /// The asset that is staked in this pool. + staking_asset_id: AssetId, + /// The asset that is distributed as rewards in this pool. + reward_asset_id: AssetId, + /// The amount of tokens distributed per block. reward_rate_per_block: Balance, + /// The total amount of tokens staked in this pool. total_tokens_staked: Balance, + /// Total accumulated rewards per share. Used when calculating payouts. accumulated_rewards_per_share: Balance, + /// Last block number the pool was updated. Used when calculating payouts. last_rewarded_block: BlockNumber, } #[frame_support::pallet(dev_mode)] pub mod pallet { use super::*; - use frame_support::pallet_prelude::*; + use codec::{EncodeLike, FullCodec}; + use frame_support::{ + pallet_prelude::*, + traits::{tokens::AssetId, Incrementable}, + }; use frame_system::pallet_prelude::*; use sp_runtime::traits::AccountIdConversion; @@ -101,24 +118,38 @@ pub mod pallet { type PalletId: Get; /// Identifier for each type of asset. - type AssetId: Member + Parameter + Clone + MaybeSerializeDeserialize + MaxEncodedLen; + type AssetId: AssetId + Member + Parameter; /// The type in which the assets are measured. type Balance: Balance + TypeInfo; + /// The origin with permission to create and manage pools. + type PoolAdminOrigin: EnsureOrigin; + /// Registry of assets that can be configured to either stake for rewards, or be offered as /// rewards for staking. type Assets: Inspect + Mutate + Balanced; + + /// The type of the unique id for each pool. + type PoolId: PartialOrd + + Incrementable + + From + + FullCodec + + Clone + + Eq + + PartialEq + + sp_std::fmt::Debug + + scale_info::TypeInfo; } - /// State of stakers in each pool. + /// State of pool stakers. #[pallet::storage] pub type PoolStakers = StorageDoubleMap< _, Blake2_128Concat, - PoolId, + T::PoolId, Blake2_128Concat, T::AccountId, PoolStakerInfo, @@ -129,65 +160,73 @@ pub mod pallet { pub type Pools = StorageMap< _, Blake2_128Concat, - PoolId, - PoolInfo>, + T::PoolId, + PoolInfo>, >; + /// Stores the [`PoolId`] to use for the next pool. + /// + /// Incremented when a new pool is created. + #[pallet::storage] + pub type NextPoolId = StorageValue<_, T::PoolId>; + #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// An account staked some tokens in a pool. Staked { - /// The account. - who: T::AccountId, + /// The account that staked assets. + staker: T::AccountId, /// The pool. - pool_id: PoolId, - /// The amount. + pool_id: T::PoolId, + /// The staked asset amount. amount: T::Balance, }, /// An account unstaked some tokens from a pool. Unstaked { - /// The account. - who: T::AccountId, + /// The account that unstaked assets. + staker: T::AccountId, /// The pool. - pool_id: PoolId, - /// The amount. + pool_id: T::PoolId, + /// The unstaked asset amount. amount: T::Balance, }, /// An account harvested some rewards. RewardsHarvested { - /// The account. - who: T::AccountId, + /// The staker whos rewards were harvested. + staker: T::AccountId, /// The pool. - pool_id: PoolId, - /// The rewarded tokens. + pool_id: T::PoolId, + /// The amount of harvested tokens. amount: T::Balance, }, /// A new reward pool was created. PoolCreated { - /// The pool. - pool_id: PoolId, + /// Unique ID for the new pool. + pool_id: T::PoolId, + /// The staking asset. + staking_asset_id: T::AssetId, + /// The reward asset. + reward_asset_id: T::AssetId, /// The initial reward rate per block. reward_rate_per_block: T::Balance, }, /// A reward pool was deleted. PoolDeleted { - /// The pool. - pool_id: PoolId, + /// The deleted pool id. + pool_id: T::PoolId, }, - /// A pool reward rate was been changed. - PoolRewardRateChanged { - /// The pool with the changed reward rate. - pool_id: PoolId, - /// The new reward rate of the reward rate per block distributed to stakers. - reward_rate_per_block: T::Balance, + /// A pool was modified. + PoolModifed { + /// The modified pool. + pool_id: T::PoolId, + /// The new reward rate. + new_reward_rate_per_block: T::Balance, }, - /// Funds were withdrawn from the Reward Pool. + /// Reward assets were withdrawn from a pool. RewardPoolWithdrawal { - /// The asset withdrawn. - reward_asset_id: T::AssetId, - /// The caller. - caller: T::AccountId, + /// The affected pool. + pool_id: T::PoolId, /// The acount of reward asset withdrawn. amount: T::Balance, }, @@ -195,8 +234,8 @@ pub mod pallet { #[pallet::error] pub enum Error { - /// TODO - TODO, + /// An operation was attempted on a non-existent pool. + NonExistentPool, } #[pallet::hooks] @@ -220,20 +259,15 @@ pub mod pallet { /// Removes an existing reward pool. /// - /// TODO decide how to manage clean up of stakers from a removed pool - pub fn remove_pool( - _origin: OriginFor, - _staked_asset_id: Box, - _reward_asset_id: Box, - ) -> DispatchResult { + /// TODO decide how to manage clean up of stakers from a removed pool. + pub fn remove_pool(_origin: OriginFor, _pool_id: T::PoolId) -> DispatchResult { todo!() } /// Stake tokens in a pool. pub fn stake( _origin: OriginFor, - _staked_asset_id: Box, - _reward_asset_id: Box, + _pool_id: T::PoolId, _amount: T::Balance, ) -> DispatchResult { todo!() @@ -242,18 +276,17 @@ pub mod pallet { /// Unstake tokens from a pool. pub fn unstake( _origin: OriginFor, - _staked_asset_id: Box, - _reward_asset_id: Box, + _pool_id: T::PoolId, _amount: T::Balance, ) -> DispatchResult { todo!() } - /// Harvest unclaimed pool rewards. + /// Harvest unclaimed pool rewards for a staker. pub fn harvest_rewards( _origin: OriginFor, - _staked_asset_id: Box, - _reward_asset_id: Box, + _staker: T::AccountId, + _pool_id: T::PoolId, ) -> DispatchResult { todo!() } @@ -261,17 +294,34 @@ pub mod pallet { /// Modify the reward rate of a pool. pub fn modify_pool( _origin: OriginFor, - _staked_asset_id: Box, - _reward_asset_id: Box, + _pool_id: T::PoolId, + _new_reward_rate: T::Balance, + ) -> DispatchResult { + todo!() + } + + /// Convinience method to deposit reward tokens into a pool. + /// + /// This method is not strictly necessary (tokens could be transferred directly to the + /// pool pot address), but is provided for convenience so manual derivation of the + /// account id is not required. + pub fn deposit_reward_tokens( + _origin: OriginFor, + _pool_id: T::PoolId, + _amount: T::Balance, ) -> DispatchResult { todo!() } } impl Pallet { - /// The account ID of the reward pot. - fn reward_pool_account_id() -> T::AccountId { - T::PalletId::get().into_account_truncating() + /// Derive a pool account ID from the pallet's ID. + fn pool_account_id(id: &T::PoolId) -> Result { + if Pools::::contains_key(id) { + Ok(T::PalletId::get().into_sub_account_truncating(id)) + } else { + Err(Error::::NonExistentPool.into()) + } } /// Update pool state in preparation for reward harvesting. From 5582a7389826a382d3bb58b4763d6816787de9dd Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Mon, 25 Mar 2024 14:06:05 +0700 Subject: [PATCH 004/159] unused imports --- substrate/frame/staking-rewards/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/substrate/frame/staking-rewards/src/lib.rs b/substrate/frame/staking-rewards/src/lib.rs index 4b282bc02059..ff4432b697d8 100644 --- a/substrate/frame/staking-rewards/src/lib.rs +++ b/substrate/frame/staking-rewards/src/lib.rs @@ -65,7 +65,7 @@ use frame_support::{ }; use scale_info::TypeInfo; use sp_core::Get; -use sp_runtime::{DispatchError, Saturating}; +use sp_runtime::DispatchError; use sp_std::boxed::Box; /// A pool staker. @@ -77,7 +77,6 @@ pub struct PoolStakerInfo { } /// A staking pool. -// #[derive(Decode, Encode, MaxEncodedLen, TypeInfo)] #[derive(Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] pub struct PoolInfo { /// The asset that is staked in this pool. @@ -97,7 +96,7 @@ pub struct PoolInfo { #[frame_support::pallet(dev_mode)] pub mod pallet { use super::*; - use codec::{EncodeLike, FullCodec}; + use codec::FullCodec; use frame_support::{ pallet_prelude::*, traits::{tokens::AssetId, Incrementable}, From 9eeebd57c1651e1b9de435a1968ad8b22e80a770 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 26 Mar 2024 17:14:22 +0700 Subject: [PATCH 005/159] add pool admins --- substrate/frame/staking-rewards/src/lib.rs | 69 ++++++++++------------ 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/substrate/frame/staking-rewards/src/lib.rs b/substrate/frame/staking-rewards/src/lib.rs index ff4432b697d8..091de5a3f635 100644 --- a/substrate/frame/staking-rewards/src/lib.rs +++ b/substrate/frame/staking-rewards/src/lib.rs @@ -68,6 +68,9 @@ use sp_core::Get; use sp_runtime::DispatchError; use sp_std::boxed::Box; +/// The type of the unique id for each pool. +pub type PoolId = u32; + /// A pool staker. #[derive(Decode, Encode, MaxEncodedLen, TypeInfo)] pub struct PoolStakerInfo { @@ -78,7 +81,7 @@ pub struct PoolStakerInfo { /// A staking pool. #[derive(Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] -pub struct PoolInfo { +pub struct PoolInfo { /// The asset that is staked in this pool. staking_asset_id: AssetId, /// The asset that is distributed as rewards in this pool. @@ -91,16 +94,14 @@ pub struct PoolInfo { accumulated_rewards_per_share: Balance, /// Last block number the pool was updated. Used when calculating payouts. last_rewarded_block: BlockNumber, + /// Permissioned account that can manage this pool. + admin: AccountId, } #[frame_support::pallet(dev_mode)] pub mod pallet { use super::*; - use codec::FullCodec; - use frame_support::{ - pallet_prelude::*, - traits::{tokens::AssetId, Incrementable}, - }; + use frame_support::{pallet_prelude::*, traits::tokens::AssetId}; use frame_system::pallet_prelude::*; use sp_runtime::traits::AccountIdConversion; @@ -122,25 +123,15 @@ pub mod pallet { /// The type in which the assets are measured. type Balance: Balance + TypeInfo; - /// The origin with permission to create and manage pools. - type PoolAdminOrigin: EnsureOrigin; + /// The origin with permission to create pools. This will be removed in a later release of + /// this pallet, which will allow permissionless pool creation. + type PermissionedPoolCreator: EnsureOrigin; /// Registry of assets that can be configured to either stake for rewards, or be offered as /// rewards for staking. type Assets: Inspect + Mutate + Balanced; - - /// The type of the unique id for each pool. - type PoolId: PartialOrd - + Incrementable - + From - + FullCodec - + Clone - + Eq - + PartialEq - + sp_std::fmt::Debug - + scale_info::TypeInfo; } /// State of pool stakers. @@ -148,7 +139,7 @@ pub mod pallet { pub type PoolStakers = StorageDoubleMap< _, Blake2_128Concat, - T::PoolId, + PoolId, Blake2_128Concat, T::AccountId, PoolStakerInfo, @@ -159,15 +150,15 @@ pub mod pallet { pub type Pools = StorageMap< _, Blake2_128Concat, - T::PoolId, - PoolInfo>, + PoolId, + PoolInfo>, >; /// Stores the [`PoolId`] to use for the next pool. /// /// Incremented when a new pool is created. #[pallet::storage] - pub type NextPoolId = StorageValue<_, T::PoolId>; + pub type NextPoolId = StorageValue<_, PoolId>; #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] @@ -177,7 +168,7 @@ pub mod pallet { /// The account that staked assets. staker: T::AccountId, /// The pool. - pool_id: T::PoolId, + pool_id: PoolId, /// The staked asset amount. amount: T::Balance, }, @@ -186,7 +177,7 @@ pub mod pallet { /// The account that unstaked assets. staker: T::AccountId, /// The pool. - pool_id: T::PoolId, + pool_id: PoolId, /// The unstaked asset amount. amount: T::Balance, }, @@ -195,14 +186,14 @@ pub mod pallet { /// The staker whos rewards were harvested. staker: T::AccountId, /// The pool. - pool_id: T::PoolId, + pool_id: PoolId, /// The amount of harvested tokens. amount: T::Balance, }, /// A new reward pool was created. PoolCreated { /// Unique ID for the new pool. - pool_id: T::PoolId, + pool_id: PoolId, /// The staking asset. staking_asset_id: T::AssetId, /// The reward asset. @@ -213,19 +204,19 @@ pub mod pallet { /// A reward pool was deleted. PoolDeleted { /// The deleted pool id. - pool_id: T::PoolId, + pool_id: PoolId, }, /// A pool was modified. PoolModifed { /// The modified pool. - pool_id: T::PoolId, + pool_id: PoolId, /// The new reward rate. new_reward_rate_per_block: T::Balance, }, /// Reward assets were withdrawn from a pool. RewardPoolWithdrawal { /// The affected pool. - pool_id: T::PoolId, + pool_id: PoolId, /// The acount of reward asset withdrawn. amount: T::Balance, }, @@ -245,6 +236,9 @@ pub mod pallet { } /// Pallet's callable functions. + /// + /// Allows optionally specifying an admin account for the pool. By default, the origin is made + /// admin. #[pallet::call] impl Pallet { /// Create a new reward pool. @@ -252,6 +246,7 @@ pub mod pallet { _origin: OriginFor, _staked_asset_id: Box, _reward_asset_id: Box, + _admin: Option, ) -> DispatchResult { todo!() } @@ -259,14 +254,14 @@ pub mod pallet { /// Removes an existing reward pool. /// /// TODO decide how to manage clean up of stakers from a removed pool. - pub fn remove_pool(_origin: OriginFor, _pool_id: T::PoolId) -> DispatchResult { + pub fn remove_pool(_origin: OriginFor, _pool_id: PoolId) -> DispatchResult { todo!() } /// Stake tokens in a pool. pub fn stake( _origin: OriginFor, - _pool_id: T::PoolId, + _pool_id: PoolId, _amount: T::Balance, ) -> DispatchResult { todo!() @@ -275,7 +270,7 @@ pub mod pallet { /// Unstake tokens from a pool. pub fn unstake( _origin: OriginFor, - _pool_id: T::PoolId, + _pool_id: PoolId, _amount: T::Balance, ) -> DispatchResult { todo!() @@ -285,7 +280,7 @@ pub mod pallet { pub fn harvest_rewards( _origin: OriginFor, _staker: T::AccountId, - _pool_id: T::PoolId, + _pool_id: PoolId, ) -> DispatchResult { todo!() } @@ -293,7 +288,7 @@ pub mod pallet { /// Modify the reward rate of a pool. pub fn modify_pool( _origin: OriginFor, - _pool_id: T::PoolId, + _pool_id: PoolId, _new_reward_rate: T::Balance, ) -> DispatchResult { todo!() @@ -306,7 +301,7 @@ pub mod pallet { /// account id is not required. pub fn deposit_reward_tokens( _origin: OriginFor, - _pool_id: T::PoolId, + _pool_id: PoolId, _amount: T::Balance, ) -> DispatchResult { todo!() @@ -315,7 +310,7 @@ pub mod pallet { impl Pallet { /// Derive a pool account ID from the pallet's ID. - fn pool_account_id(id: &T::PoolId) -> Result { + fn pool_account_id(id: &PoolId) -> Result { if Pools::::contains_key(id) { Ok(T::PalletId::get().into_sub_account_truncating(id)) } else { From 19cd1d2f018c308d536dde51a83d0866d1ded0a8 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Thu, 28 Mar 2024 17:05:33 +0700 Subject: [PATCH 006/159] create_pool implementation, mock and test set up --- substrate/frame/staking-rewards/src/lib.rs | 81 ++++++--- substrate/frame/staking-rewards/src/mock.rs | 168 +++++++++++++++++++ substrate/frame/staking-rewards/src/tests.rs | 163 ++++++++++++++++++ 3 files changed, 392 insertions(+), 20 deletions(-) create mode 100644 substrate/frame/staking-rewards/src/mock.rs create mode 100644 substrate/frame/staking-rewards/src/tests.rs diff --git a/substrate/frame/staking-rewards/src/lib.rs b/substrate/frame/staking-rewards/src/lib.rs index 091de5a3f635..7e1fbfa46441 100644 --- a/substrate/frame/staking-rewards/src/lib.rs +++ b/substrate/frame/staking-rewards/src/lib.rs @@ -68,6 +68,11 @@ use sp_core::Get; use sp_runtime::DispatchError; use sp_std::boxed::Box; +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; + /// The type of the unique id for each pool. pub type PoolId = u32; @@ -80,7 +85,7 @@ pub struct PoolStakerInfo { } /// A staking pool. -#[derive(Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] +#[derive(Debug, Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] pub struct PoolInfo { /// The asset that is staked in this pool. staking_asset_id: AssetId, @@ -103,7 +108,7 @@ pub mod pallet { use super::*; use frame_support::{pallet_prelude::*, traits::tokens::AssetId}; use frame_system::pallet_prelude::*; - use sp_runtime::traits::AccountIdConversion; + use sp_runtime::traits::{AccountIdConversion, Saturating}; #[pallet::pallet] pub struct Pallet(_); @@ -158,7 +163,7 @@ pub mod pallet { /// /// Incremented when a new pool is created. #[pallet::storage] - pub type NextPoolId = StorageValue<_, PoolId>; + pub type NextPoolId = StorageValue<_, PoolId, ValueQuery>; #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] @@ -166,7 +171,7 @@ pub mod pallet { /// An account staked some tokens in a pool. Staked { /// The account that staked assets. - staker: T::AccountId, + who: T::AccountId, /// The pool. pool_id: PoolId, /// The staked asset amount. @@ -175,7 +180,7 @@ pub mod pallet { /// An account unstaked some tokens from a pool. Unstaked { /// The account that unstaked assets. - staker: T::AccountId, + who: T::AccountId, /// The pool. pool_id: PoolId, /// The unstaked asset amount. @@ -183,6 +188,8 @@ pub mod pallet { }, /// An account harvested some rewards. RewardsHarvested { + /// The extrinsic caller. + who: T::AccountId, /// The staker whos rewards were harvested. staker: T::AccountId, /// The pool. @@ -192,6 +199,8 @@ pub mod pallet { }, /// A new reward pool was created. PoolCreated { + /// The account that created the pool. + creator: T::AccountId, /// Unique ID for the new pool. pool_id: PoolId, /// The staking asset. @@ -200,26 +209,21 @@ pub mod pallet { reward_asset_id: T::AssetId, /// The initial reward rate per block. reward_rate_per_block: T::Balance, + /// The account allowed to modify the pool. + admin: T::AccountId, }, - /// A reward pool was deleted. + /// A reward pool was deleted by the admin. PoolDeleted { /// The deleted pool id. pool_id: PoolId, }, - /// A pool was modified. + /// A pool was modified by the admin. PoolModifed { /// The modified pool. pool_id: PoolId, /// The new reward rate. new_reward_rate_per_block: T::Balance, }, - /// Reward assets were withdrawn from a pool. - RewardPoolWithdrawal { - /// The affected pool. - pool_id: PoolId, - /// The acount of reward asset withdrawn. - amount: T::Balance, - }, } #[pallet::error] @@ -231,7 +235,7 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { fn integrity_test() { - todo!() + // TODO: Proper implementation } } @@ -243,12 +247,49 @@ pub mod pallet { impl Pallet { /// Create a new reward pool. pub fn create_pool( - _origin: OriginFor, - _staked_asset_id: Box, - _reward_asset_id: Box, - _admin: Option, + origin: OriginFor, + staked_asset_id: Box, + reward_asset_id: Box, + reward_rate_per_block: T::Balance, + admin: Option, ) -> DispatchResult { - todo!() + // Ensure Origin is allowed to create pools. + T::PermissionedPoolCreator::ensure_origin(origin.clone())?; + + // Get the admin, or try to use the origin as admin. + let origin_acc_id = ensure_signed(origin)?; + let admin = match admin { + Some(admin) => admin, + None => origin_acc_id, + }; + + // Create the pool. + let pool = PoolInfo::> { + staking_asset_id: *staked_asset_id.clone(), + reward_asset_id: *reward_asset_id.clone(), + reward_rate_per_block, + total_tokens_staked: 0u32.into(), + accumulated_rewards_per_share: 0u32.into(), + last_rewarded_block: 0u32.into(), + admin: admin.clone(), + }; + + // Insert the pool into storage. + let pool_id = NextPoolId::::get(); + Pools::::insert(pool_id, pool); + NextPoolId::::put(pool_id.saturating_add(1)); + + // Emit the event. + Self::deposit_event(Event::PoolCreated { + creator: origin_acc_id, + pool_id, + staking_asset_id: *staked_asset_id, + reward_asset_id: *reward_asset_id, + reward_rate_per_block, + admin, + }); + + Ok(()) } /// Removes an existing reward pool. diff --git a/substrate/frame/staking-rewards/src/mock.rs b/substrate/frame/staking-rewards/src/mock.rs new file mode 100644 index 000000000000..658d1bb68426 --- /dev/null +++ b/substrate/frame/staking-rewards/src/mock.rs @@ -0,0 +1,168 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Test environment for Staking Rewards pallet. + +use super::*; +use crate as pallet_staking_rewards; +use core::default::Default; +use frame_support::{ + construct_runtime, derive_impl, + instances::Instance1, + ord_parameter_types, parameter_types, + traits::{ + tokens::fungible::{NativeFromLeft, NativeOrWithId, UnionOf}, + AsEnsureOriginWithArg, ConstU128, ConstU32, EnsureOrigin, + }, + PalletId, +}; +use frame_system::{ensure_signed, EnsureSigned}; +use sp_runtime::{ + traits::{AccountIdConversion, IdentityLookup}, + BuildStorage, +}; + +type Block = frame_system::mocking::MockBlock; + +construct_runtime!( + pub enum MockRuntime + { + System: frame_system, + Balances: pallet_balances, + Assets: pallet_assets::, + StakingRewards: pallet_staking_rewards, + } +); + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] +impl frame_system::Config for MockRuntime { + type AccountId = u128; + type Lookup = IdentityLookup; + type Block = Block; + type AccountData = pallet_balances::AccountData; +} + +impl pallet_balances::Config for MockRuntime { + type Balance = u128; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU128<100>; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = (); + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 8]; + type FreezeIdentifier = (); + type MaxFreezes = (); + type RuntimeHoldReason = (); + type RuntimeFreezeReason = (); +} + +impl pallet_assets::Config for MockRuntime { + type RuntimeEvent = RuntimeEvent; + type Balance = u128; + type RemoveItemsLimit = ConstU32<1000>; + type AssetId = u32; + type AssetIdParameter = u32; + type Currency = Balances; + type CreateOrigin = AsEnsureOriginWithArg>; + type ForceOrigin = frame_system::EnsureRoot; + type AssetDeposit = ConstU128<1>; + type AssetAccountDeposit = ConstU128<10>; + type MetadataDepositBase = ConstU128<1>; + type MetadataDepositPerByte = ConstU128<1>; + type ApprovalDeposit = ConstU128<1>; + type StringLimit = ConstU32<50>; + type Freezer = (); + type Extra = (); + type WeightInfo = (); + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = (); + } +} + +parameter_types! { + pub const StakingRewardsPalletId: PalletId = PalletId(*b"py/stkrd"); + pub const Native: NativeOrWithId = NativeOrWithId::Native; + pub const PermissionedAccountId: u128 = 1; +} +ord_parameter_types! { + pub const AssetConversionOrigin: u128 = AccountIdConversion::::into_account_truncating(&StakingRewardsPalletId::get()); +} + +pub struct MockPermissionedPoolCreator; +impl EnsureOrigin for MockPermissionedPoolCreator { + type Success = (); + + fn try_origin( + origin: RuntimeOrigin, + // key: &RuntimeParametersKey, + ) -> Result { + // Set account 1 to admin in tests + if ensure_signed(origin.clone()).map_or(false, |acc| acc == 1) { + return Ok(()); + } + + return Err(origin); + } + + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin() -> Result { + todo!() + } +} + +pub type NativeAndAssets = UnionOf, u128>; + +impl Config for MockRuntime { + type RuntimeEvent = RuntimeEvent; + type AssetId = NativeOrWithId; + type Balance = ::Balance; + type Assets = NativeAndAssets; + type PalletId = StakingRewardsPalletId; + // allow account id 1 to be permissioned creator + type PermissionedPoolCreator = MockPermissionedPoolCreator; +} + +pub(crate) fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + // pallet_assets::GenesisConfig:: { + // // Genesis assets: id, owner, is_sufficient, min_balance + // // pub assets: Vec<(T::AssetId, T::AccountId, bool, T::Balance)>, + // assets: vec![(1, 1, true, 10000)], + // // Genesis metadata: id, name, symbol, decimals + // // pub metadata: Vec<(T::AssetId, Vec, Vec, u8)>, + // metadata: vec![(1, b"test".to_vec(), b"TST".to_vec(), 18)], + // // Genesis accounts: id, account_id, balance + // // pub accounts: Vec<(T::AssetId, T::AccountId, T::Balance)>, + // accounts: vec![(1, 1, 10000)], + // } + // .assimilate_storage(&mut t) + // .unwrap(); + + pallet_balances::GenesisConfig:: { + balances: vec![(1, 10000), (2, 20000), (3, 30000), (4, 40000)], + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} diff --git a/substrate/frame/staking-rewards/src/tests.rs b/substrate/frame/staking-rewards/src/tests.rs new file mode 100644 index 000000000000..18e1f86b516b --- /dev/null +++ b/substrate/frame/staking-rewards/src/tests.rs @@ -0,0 +1,163 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{mock::*, *}; +use frame_support::{assert_ok, traits::fungible::NativeOrWithId}; + +fn create_tokens(owner: u128, tokens: Vec>) { + create_tokens_with_ed(owner, tokens, 1) +} + +fn create_tokens_with_ed(owner: u128, tokens: Vec>, ed: u128) { + for token_id in tokens { + let asset_id = match token_id { + NativeOrWithId::WithId(id) => id, + _ => unreachable!("invalid token"), + }; + assert_ok!(Assets::force_create(RuntimeOrigin::root(), asset_id, owner, false, ed)); + } +} + +fn events() -> Vec> { + let result = System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| { + if let mock::RuntimeEvent::StakingRewards(inner) = e { + Some(inner) + } else { + None + } + }) + .collect(); + + System::reset_events(); + + result +} + +fn pools() -> Vec<(u32, PoolInfo, u128, u64>)> { + Pools::::iter().collect() +} + +#[test] +fn create_pool_works() { + new_test_ext().execute_with(|| { + // Setup + let user = 1; + let staking_asset_id = NativeOrWithId::::Native; + let reward_asset_id = NativeOrWithId::::WithId(1); + let reward_rate_per_block = 100; + + create_tokens(user, vec![reward_asset_id.clone()]); + assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), user, 1000)); + + // Create a pool with default admin. + assert_eq!(NextPoolId::::get(), 0); + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::signed(user), + Box::new(staking_asset_id.clone()), + Box::new(reward_asset_id.clone()), + reward_rate_per_block, + None + )); + + // Event is emitted. + assert_eq!( + events(), + [Event::::PoolCreated { + pool_id: 0, + staking_asset_id: staking_asset_id.clone(), + reward_asset_id: reward_asset_id.clone(), + reward_rate_per_block, + admin: user, + }] + ); + + // State is updated correctly. + assert_eq!(NextPoolId::::get(), 1); + assert_eq!( + pools(), + vec![( + 0, + PoolInfo { + staking_asset_id: staking_asset_id.clone(), + reward_asset_id: reward_asset_id.clone(), + reward_rate_per_block, + admin: user, + total_tokens_staked: 0, + accumulated_rewards_per_share: 0, + last_rewarded_block: 0 + } + )] + ); + + // Create another pool with explicit admin. + let admin = 2; + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::signed(user), + Box::new(staking_asset_id.clone()), + Box::new(reward_asset_id.clone()), + reward_rate_per_block, + Some(admin) + )); + + // Event is emitted. + assert_eq!( + events(), + [Event::::PoolCreated { + pool_id: 1, + staking_asset_id: staking_asset_id.clone(), + reward_asset_id: reward_asset_id.clone(), + reward_rate_per_block, + admin, + }] + ); + + // State is updated correctly. + assert_eq!(NextPoolId::::get(), 2); + assert_eq!( + pools(), + vec![ + ( + 0, + PoolInfo { + staking_asset_id: staking_asset_id.clone(), + reward_asset_id: reward_asset_id.clone(), + reward_rate_per_block, + admin: user, + total_tokens_staked: 0, + accumulated_rewards_per_share: 0, + last_rewarded_block: 0 + } + ), + ( + 1, + PoolInfo { + staking_asset_id, + reward_asset_id, + reward_rate_per_block, + admin, + total_tokens_staked: 0, + accumulated_rewards_per_share: 0, + last_rewarded_block: 0 + } + ) + ] + ); + }); +} From b0cd831893e776c947308488512acb8e9c846760 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Thu, 28 Mar 2024 17:20:16 +0700 Subject: [PATCH 007/159] update tests --- substrate/frame/staking-rewards/src/lib.rs | 2 +- substrate/frame/staking-rewards/src/tests.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/substrate/frame/staking-rewards/src/lib.rs b/substrate/frame/staking-rewards/src/lib.rs index 7e1fbfa46441..72f0466576ea 100644 --- a/substrate/frame/staking-rewards/src/lib.rs +++ b/substrate/frame/staking-rewards/src/lib.rs @@ -260,7 +260,7 @@ pub mod pallet { let origin_acc_id = ensure_signed(origin)?; let admin = match admin { Some(admin) => admin, - None => origin_acc_id, + None => origin_acc_id.clone(), }; // Create the pool. diff --git a/substrate/frame/staking-rewards/src/tests.rs b/substrate/frame/staking-rewards/src/tests.rs index 18e1f86b516b..1a9cb2a9682f 100644 --- a/substrate/frame/staking-rewards/src/tests.rs +++ b/substrate/frame/staking-rewards/src/tests.rs @@ -80,6 +80,7 @@ fn create_pool_works() { assert_eq!( events(), [Event::::PoolCreated { + creator: user, pool_id: 0, staking_asset_id: staking_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), @@ -120,6 +121,7 @@ fn create_pool_works() { assert_eq!( events(), [Event::::PoolCreated { + creator: user, pool_id: 1, staking_asset_id: staking_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), From d1bf78f6aa1e5c4eb04eb72440381648bf5ca66e Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Thu, 28 Mar 2024 17:27:46 +0700 Subject: [PATCH 008/159] add check for asset existence --- substrate/frame/staking-rewards/src/lib.rs | 12 ++++++ substrate/frame/staking-rewards/src/tests.rs | 43 +++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/substrate/frame/staking-rewards/src/lib.rs b/substrate/frame/staking-rewards/src/lib.rs index 72f0466576ea..9504eda34785 100644 --- a/substrate/frame/staking-rewards/src/lib.rs +++ b/substrate/frame/staking-rewards/src/lib.rs @@ -230,6 +230,8 @@ pub mod pallet { pub enum Error { /// An operation was attempted on a non-existent pool. NonExistentPool, + /// An operation was attempted using a non-existent asset. + NonExistentAsset, } #[pallet::hooks] @@ -256,6 +258,16 @@ pub mod pallet { // Ensure Origin is allowed to create pools. T::PermissionedPoolCreator::ensure_origin(origin.clone())?; + // Ensure the assets exist. + ensure!( + T::Assets::asset_exists(*staked_asset_id.clone()), + Error::::NonExistentAsset + ); + ensure!( + T::Assets::asset_exists(*reward_asset_id.clone()), + Error::::NonExistentAsset + ); + // Get the admin, or try to use the origin as admin. let origin_acc_id = ensure_signed(origin)?; let admin = match admin { diff --git a/substrate/frame/staking-rewards/src/tests.rs b/substrate/frame/staking-rewards/src/tests.rs index 1a9cb2a9682f..bf2d66940ebc 100644 --- a/substrate/frame/staking-rewards/src/tests.rs +++ b/substrate/frame/staking-rewards/src/tests.rs @@ -16,7 +16,7 @@ // limitations under the License. use crate::{mock::*, *}; -use frame_support::{assert_ok, traits::fungible::NativeOrWithId}; +use frame_support::{assert_err, assert_ok, traits::fungible::NativeOrWithId}; fn create_tokens(owner: u128, tokens: Vec>) { create_tokens_with_ed(owner, tokens, 1) @@ -163,3 +163,44 @@ fn create_pool_works() { ); }); } + +#[test] +fn create_pool_with_non_existent_asset_fails() { + new_test_ext().execute_with(|| { + let valid_asset = NativeOrWithId::::WithId(1); + let invalid_asset = NativeOrWithId::::WithId(200); + + assert_err!( + StakingRewards::create_pool( + RuntimeOrigin::signed(1), + Box::new(valid_asset.clone()), + Box::new(invalid_asset.clone()), + 10, + None + ), + Error::::NonExistentAsset + ); + + assert_err!( + StakingRewards::create_pool( + RuntimeOrigin::signed(1), + Box::new(invalid_asset.clone()), + Box::new(valid_asset.clone()), + 10, + None + ), + Error::::NonExistentAsset + ); + + assert_err!( + StakingRewards::create_pool( + RuntimeOrigin::signed(1), + Box::new(invalid_asset.clone()), + Box::new(invalid_asset.clone()), + 10, + None + ), + Error::::NonExistentAsset + ); + }) +} From bf1f5c803e298452c9406b72a7eec28b024919c0 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Mon, 1 Apr 2024 16:54:21 +0400 Subject: [PATCH 009/159] wip logic --- substrate/frame/staking-rewards/src/lib.rs | 201 +++++++++-- substrate/frame/staking-rewards/src/tests.rs | 341 ++++++++++++------- 2 files changed, 377 insertions(+), 165 deletions(-) diff --git a/substrate/frame/staking-rewards/src/lib.rs b/substrate/frame/staking-rewards/src/lib.rs index 9504eda34785..b74d4b50eb46 100644 --- a/substrate/frame/staking-rewards/src/lib.rs +++ b/substrate/frame/staking-rewards/src/lib.rs @@ -76,12 +76,18 @@ mod tests; /// The type of the unique id for each pool. pub type PoolId = u32; +/// Multiplier to maintain precision when calculating rewards. +pub(crate) const PRECISION_SCALING_FACTOR: u32 = u32::MAX; + /// A pool staker. -#[derive(Decode, Encode, MaxEncodedLen, TypeInfo)] +#[derive(Default, Decode, Encode, MaxEncodedLen, TypeInfo)] pub struct PoolStakerInfo { + /// Amount of tokens staked. amount: Balance, + /// Accumulated, unpaid rewards. rewards: Balance, - reward_debt: Balance, + /// Reward per token value at the time of the staker's last interaction with the contract. + reward_per_token_paid: Balance, } /// A staking pool. @@ -95,20 +101,24 @@ pub struct PoolInfo { reward_rate_per_block: Balance, /// The total amount of tokens staked in this pool. total_tokens_staked: Balance, - /// Total accumulated rewards per share. Used when calculating payouts. - accumulated_rewards_per_share: Balance, + /// Total rewards accumulated per token, up to the last time the rewards were updated. + reward_per_token_stored: Balance, /// Last block number the pool was updated. Used when calculating payouts. - last_rewarded_block: BlockNumber, + last_update_block: BlockNumber, /// Permissioned account that can manage this pool. admin: AccountId, } #[frame_support::pallet(dev_mode)] pub mod pallet { + use super::*; - use frame_support::{pallet_prelude::*, traits::tokens::AssetId}; + use frame_support::{ + pallet_prelude::*, + traits::tokens::{AssetId, Preservation}, + }; use frame_system::pallet_prelude::*; - use sp_runtime::traits::{AccountIdConversion, Saturating}; + use sp_runtime::traits::{AccountIdConversion, EnsureDiv, Saturating}; #[pallet::pallet] pub struct Pallet(_); @@ -232,6 +242,8 @@ pub mod pallet { NonExistentPool, /// An operation was attempted using a non-existent asset. NonExistentAsset, + /// There was an error converting a block number. + BlockNumberConversionError, } #[pallet::hooks] @@ -268,7 +280,7 @@ pub mod pallet { Error::::NonExistentAsset ); - // Get the admin, or try to use the origin as admin. + // Get the admin, defaulting to the origin. let origin_acc_id = ensure_signed(origin)?; let admin = match admin { Some(admin) => admin, @@ -281,17 +293,17 @@ pub mod pallet { reward_asset_id: *reward_asset_id.clone(), reward_rate_per_block, total_tokens_staked: 0u32.into(), - accumulated_rewards_per_share: 0u32.into(), - last_rewarded_block: 0u32.into(), + reward_per_token_stored: 0u32.into(), + last_update_block: 0u32.into(), admin: admin.clone(), }; - // Insert the pool into storage. + // Insert it into storage. let pool_id = NextPoolId::::get(); Pools::::insert(pool_id, pool); NextPoolId::::put(pool_id.saturating_add(1)); - // Emit the event. + // Emit created event. Self::deposit_event(Event::PoolCreated { creator: origin_acc_id, pool_id, @@ -312,30 +324,86 @@ pub mod pallet { } /// Stake tokens in a pool. - pub fn stake( - _origin: OriginFor, - _pool_id: PoolId, - _amount: T::Balance, - ) -> DispatchResult { - todo!() + pub fn stake(origin: OriginFor, pool_id: PoolId, amount: T::Balance) -> DispatchResult { + let caller = ensure_signed(origin)?; + + // Always start by updating the pool rewards. + Self::update_pool_rewards(&pool_id, &caller)?; + + // Try to freeze the staker assets. + // TODO: (blocked https://github.com/paritytech/polkadot-sdk/issues/3342) + + // Update Pools. + let mut pool = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + pool.total_tokens_staked.saturating_accrue(amount); + Pools::::insert(pool_id, pool); + + // Update PoolStakers. + let mut staker = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); + staker.amount.saturating_accrue(amount); + PoolStakers::::insert(pool_id, &caller, staker); + + Ok(()) } /// Unstake tokens from a pool. pub fn unstake( - _origin: OriginFor, - _pool_id: PoolId, - _amount: T::Balance, + origin: OriginFor, + pool_id: PoolId, + amount: T::Balance, ) -> DispatchResult { - todo!() + let caller = ensure_signed(origin)?; + + // Always start by updating the pool rewards. + Self::update_pool_rewards(&pool_id, &caller)?; + + // Unfreeze staker assets. + // TODO: (blocked https://github.com/paritytech/polkadot-sdk/issues/3342) + + // Update Pools. + let mut pool = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + pool.total_tokens_staked.saturating_reduce(amount); + + // Update PoolStakers. + let mut staker = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); + staker.amount.saturating_reduce(amount); + + Ok(()) } /// Harvest unclaimed pool rewards for a staker. pub fn harvest_rewards( - _origin: OriginFor, - _staker: T::AccountId, - _pool_id: PoolId, + origin: OriginFor, + pool_id: PoolId, + staker: Option, ) -> DispatchResult { - todo!() + let caller = ensure_signed(origin)?; + + let staker = match staker { + Some(staker) => staker, + None => caller.clone(), + }; + + // Always start by updating the pool rewards. + Self::update_pool_rewards(&pool_id, &staker)?; + + // Transfer unclaimed rewards from the pool to the staker. + let mut staker_info = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); + let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + let pool_account_id = Self::pool_account_id(&pool_id)?; + + T::Assets::transfer( + pool_info.reward_asset_id, + &pool_account_id, + &staker, + staker_info.rewards, + Preservation::Preserve, + )?; + + // Reset staker unclaimed rewards. + staker_info.rewards = 0u32.into(); + + Ok(()) } /// Modify the reward rate of a pool. @@ -353,11 +421,21 @@ pub mod pallet { /// pool pot address), but is provided for convenience so manual derivation of the /// account id is not required. pub fn deposit_reward_tokens( - _origin: OriginFor, - _pool_id: PoolId, - _amount: T::Balance, + origin: OriginFor, + pool_id: PoolId, + amount: T::Balance, ) -> DispatchResult { - todo!() + let caller = ensure_signed(origin)?; + let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + let pool_account_id = Self::pool_account_id(&pool_id)?; + T::Assets::transfer( + pool_info.reward_asset_id, + &caller, + &pool_account_id, + amount, + Preservation::Preserve, + )?; + Ok(()) } } @@ -371,9 +449,66 @@ pub mod pallet { } } - /// Update pool state in preparation for reward harvesting. - fn update_pool_rewards(_staked_asset_id: T::AssetId, _reward_asset_id: T::AssetId) { - todo!() + /// Update pool reward state. + fn update_pool_rewards(pool_id: &PoolId, staker: &T::AccountId) -> DispatchResult { + let reward_per_token = Self::reward_per_token(pool_id)?; + + let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + pool_info.last_update_block = frame_system::Pallet::::block_number(); + Pools::::insert(pool_id, pool_info); + + let mut staker_info = PoolStakers::::get(pool_id, staker).unwrap_or_default(); + staker_info.rewards = Self::derive_rewards(pool_id, staker)?; + staker_info.reward_per_token_paid = reward_per_token; + PoolStakers::::insert(pool_id, staker, staker_info); + + Ok(()) + } + + /// Derives the current reward per token for this pool. + /// + /// Helper function for update_pool_rewards. Should not be called directly. + fn reward_per_token(pool_id: &PoolId) -> Result { + let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + + if pool_info.total_tokens_staked.eq(&0u32.into()) { + return Ok(0u32.into()); + } + + let blocks_elapsed: u32 = match frame_system::Pallet::::block_number() + .saturating_sub(pool_info.last_update_block) + .try_into() + { + Ok(b) => b, + Err(_) => return Err(Error::::BlockNumberConversionError.into()), + }; + + Ok(pool_info + .reward_per_token_stored + .saturating_add( + pool_info + .reward_rate_per_block + .saturating_mul(blocks_elapsed.into()) + .saturating_mul(PRECISION_SCALING_FACTOR.into()), + ) + .ensure_div(pool_info.total_tokens_staked)?) + } + + /// Derives the amount of rewards earned by a staker. + /// + /// Helper function for update_pool_rewards. Should not be called directly. + fn derive_rewards( + pool_id: &PoolId, + staker: &T::AccountId, + ) -> Result { + let reward_per_token = Self::reward_per_token(pool_id)?; + let staker_info = PoolStakers::::get(pool_id, staker).unwrap_or_default(); + + Ok(staker_info + .amount + .saturating_mul(reward_per_token.saturating_sub(staker_info.reward_per_token_paid)) + .ensure_div(PRECISION_SCALING_FACTOR.into())? + .saturating_add(staker_info.rewards)) } } } diff --git a/substrate/frame/staking-rewards/src/tests.rs b/substrate/frame/staking-rewards/src/tests.rs index bf2d66940ebc..1494f1c776b4 100644 --- a/substrate/frame/staking-rewards/src/tests.rs +++ b/substrate/frame/staking-rewards/src/tests.rs @@ -54,88 +54,49 @@ fn pools() -> Vec<(u32, PoolInfo, u128, u64>)> { Pools::::iter().collect() } -#[test] -fn create_pool_works() { - new_test_ext().execute_with(|| { - // Setup - let user = 1; - let staking_asset_id = NativeOrWithId::::Native; - let reward_asset_id = NativeOrWithId::::WithId(1); - let reward_rate_per_block = 100; - - create_tokens(user, vec![reward_asset_id.clone()]); - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), user, 1000)); - - // Create a pool with default admin. - assert_eq!(NextPoolId::::get(), 0); - assert_ok!(StakingRewards::create_pool( - RuntimeOrigin::signed(user), - Box::new(staking_asset_id.clone()), - Box::new(reward_asset_id.clone()), - reward_rate_per_block, - None - )); - - // Event is emitted. - assert_eq!( - events(), - [Event::::PoolCreated { - creator: user, - pool_id: 0, - staking_asset_id: staking_asset_id.clone(), - reward_asset_id: reward_asset_id.clone(), +mod create_pool { + use super::*; + + #[test] + fn success() { + new_test_ext().execute_with(|| { + // Setup + let user = 1; + let staking_asset_id = NativeOrWithId::::Native; + let reward_asset_id = NativeOrWithId::::WithId(1); + let reward_rate_per_block = 100; + + create_tokens(user, vec![reward_asset_id.clone()]); + assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), user, 1000)); + + // Create a pool with default admin. + assert_eq!(NextPoolId::::get(), 0); + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::signed(user), + Box::new(staking_asset_id.clone()), + Box::new(reward_asset_id.clone()), reward_rate_per_block, - admin: user, - }] - ); - - // State is updated correctly. - assert_eq!(NextPoolId::::get(), 1); - assert_eq!( - pools(), - vec![( - 0, - PoolInfo { + None + )); + + // Event is emitted. + assert_eq!( + events(), + [Event::::PoolCreated { + creator: user, + pool_id: 0, staking_asset_id: staking_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, admin: user, - total_tokens_staked: 0, - accumulated_rewards_per_share: 0, - last_rewarded_block: 0 - } - )] - ); - - // Create another pool with explicit admin. - let admin = 2; - assert_ok!(StakingRewards::create_pool( - RuntimeOrigin::signed(user), - Box::new(staking_asset_id.clone()), - Box::new(reward_asset_id.clone()), - reward_rate_per_block, - Some(admin) - )); - - // Event is emitted. - assert_eq!( - events(), - [Event::::PoolCreated { - creator: user, - pool_id: 1, - staking_asset_id: staking_asset_id.clone(), - reward_asset_id: reward_asset_id.clone(), - reward_rate_per_block, - admin, - }] - ); - - // State is updated correctly. - assert_eq!(NextPoolId::::get(), 2); - assert_eq!( - pools(), - vec![ - ( + }] + ); + + // State is updated correctly. + assert_eq!(NextPoolId::::get(), 1); + assert_eq!( + pools(), + vec![( 0, PoolInfo { staking_asset_id: staking_asset_id.clone(), @@ -143,64 +104,180 @@ fn create_pool_works() { reward_rate_per_block, admin: user, total_tokens_staked: 0, - accumulated_rewards_per_share: 0, - last_rewarded_block: 0 + reward_per_token_stored: 0, + last_update_block: 0 } + )] + ); + + // Create another pool with explicit admin. + let admin = 2; + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::signed(user), + Box::new(staking_asset_id.clone()), + Box::new(reward_asset_id.clone()), + reward_rate_per_block, + Some(admin) + )); + + // Event is emitted. + assert_eq!( + events(), + [Event::::PoolCreated { + creator: user, + pool_id: 1, + staking_asset_id: staking_asset_id.clone(), + reward_asset_id: reward_asset_id.clone(), + reward_rate_per_block, + admin, + }] + ); + + // State is updated correctly. + assert_eq!(NextPoolId::::get(), 2); + assert_eq!( + pools(), + vec![ + ( + 0, + PoolInfo { + staking_asset_id: staking_asset_id.clone(), + reward_asset_id: reward_asset_id.clone(), + reward_rate_per_block, + admin: user, + total_tokens_staked: 0, + reward_per_token_stored: 0, + last_update_block: 0 + } + ), + ( + 1, + PoolInfo { + staking_asset_id, + reward_asset_id, + reward_rate_per_block, + admin, + total_tokens_staked: 0, + reward_per_token_stored: 0, + last_update_block: 0 + } + ) + ] + ); + }); + } + + #[test] + fn non_existent_asset_fails() { + new_test_ext().execute_with(|| { + let valid_asset = NativeOrWithId::::WithId(1); + let invalid_asset = NativeOrWithId::::WithId(200); + + assert_err!( + StakingRewards::create_pool( + RuntimeOrigin::signed(1), + Box::new(valid_asset.clone()), + Box::new(invalid_asset.clone()), + 10, + None ), - ( - 1, - PoolInfo { - staking_asset_id, - reward_asset_id, - reward_rate_per_block, - admin, - total_tokens_staked: 0, - accumulated_rewards_per_share: 0, - last_rewarded_block: 0 - } - ) - ] - ); - }); + Error::::NonExistentAsset + ); + + assert_err!( + StakingRewards::create_pool( + RuntimeOrigin::signed(1), + Box::new(invalid_asset.clone()), + Box::new(valid_asset.clone()), + 10, + None + ), + Error::::NonExistentAsset + ); + + assert_err!( + StakingRewards::create_pool( + RuntimeOrigin::signed(1), + Box::new(invalid_asset.clone()), + Box::new(invalid_asset.clone()), + 10, + None + ), + Error::::NonExistentAsset + ); + }) + } } -#[test] -fn create_pool_with_non_existent_asset_fails() { - new_test_ext().execute_with(|| { - let valid_asset = NativeOrWithId::::WithId(1); - let invalid_asset = NativeOrWithId::::WithId(200); - - assert_err!( - StakingRewards::create_pool( - RuntimeOrigin::signed(1), - Box::new(valid_asset.clone()), - Box::new(invalid_asset.clone()), - 10, - None - ), - Error::::NonExistentAsset - ); - - assert_err!( - StakingRewards::create_pool( - RuntimeOrigin::signed(1), - Box::new(invalid_asset.clone()), - Box::new(valid_asset.clone()), - 10, - None - ), - Error::::NonExistentAsset - ); - - assert_err!( - StakingRewards::create_pool( - RuntimeOrigin::signed(1), - Box::new(invalid_asset.clone()), - Box::new(invalid_asset.clone()), - 10, +mod stake { + use super::*; + + #[test] + fn success() { + new_test_ext().execute_with(|| { + // Setup + let user = 1; + let staking_asset_id = NativeOrWithId::::WithId(1); + let reward_asset_id = NativeOrWithId::::Native; + let reward_rate_per_block = 100; + + create_tokens(user, vec![staking_asset_id.clone()]); + + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::signed(user), + Box::new(staking_asset_id.clone()), + Box::new(reward_asset_id.clone()), + reward_rate_per_block, None - ), - Error::::NonExistentAsset - ); - }) + )); + + let pool_id = 0; + + // User stakes tokens + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(user), pool_id, 1000)); + + // Check that the user's staked amount is updated + assert_eq!(PoolStakers::::get(pool_id, user).unwrap().amount, 1000); + + // Check that the pool's total tokens staked is updated + assert_eq!(Pools::::get(pool_id).unwrap().total_tokens_staked, 1000); + + // TODO: Check user's frozen balance is updated + + // User stakes more tokens + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(user), pool_id, 500)); + + // Check that the user's staked amount is updated + assert_eq!(PoolStakers::::get(pool_id, user).unwrap().amount, 1500); + + // Check that the pool's total tokens staked is updated + assert_eq!(Pools::::get(pool_id).unwrap().total_tokens_staked, 1500); + + // TODO: Check user's frozen balance is updated + }); + } + + #[test] + fn non_existent_pool() { + new_test_ext().execute_with(|| { + // Setup + let user = 1; + let staking_asset_id = NativeOrWithId::::WithId(1); + + create_tokens(user, vec![staking_asset_id.clone()]); + + let non_existent_pool_id = 999; + + // User tries to stake tokens in a non-existent pool + assert_err!( + StakingRewards::stake(RuntimeOrigin::signed(user), non_existent_pool_id, 1000), + Error::::NonExistentPool + ); + }); + } + + #[test] + fn insufficient_balance() { + // TODO: When we're able to freeze assets. + } } From b92116647a6a352ef414b16c6063e1ff9f21668b Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Mon, 1 Apr 2024 17:04:32 +0400 Subject: [PATCH 010/159] unstake tests --- substrate/frame/staking-rewards/src/lib.rs | 9 +- substrate/frame/staking-rewards/src/tests.rs | 127 ++++++++++++++++++- 2 files changed, 128 insertions(+), 8 deletions(-) diff --git a/substrate/frame/staking-rewards/src/lib.rs b/substrate/frame/staking-rewards/src/lib.rs index b74d4b50eb46..1883b1dffba0 100644 --- a/substrate/frame/staking-rewards/src/lib.rs +++ b/substrate/frame/staking-rewards/src/lib.rs @@ -238,6 +238,8 @@ pub mod pallet { #[pallet::error] pub enum Error { + /// The staker does not have enough tokens to perform the operation. + NotEnoughTokens, /// An operation was attempted on a non-existent pool. NonExistentPool, /// An operation was attempted using a non-existent asset. @@ -357,16 +359,21 @@ pub mod pallet { // Always start by updating the pool rewards. Self::update_pool_rewards(&pool_id, &caller)?; + // Check the staker has enough staked tokens. + let mut staker = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); + ensure!(staker.amount >= amount, Error::::NotEnoughTokens); + // Unfreeze staker assets. // TODO: (blocked https://github.com/paritytech/polkadot-sdk/issues/3342) // Update Pools. let mut pool = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; pool.total_tokens_staked.saturating_reduce(amount); + Pools::::insert(pool_id, pool); // Update PoolStakers. - let mut staker = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); staker.amount.saturating_reduce(amount); + PoolStakers::::insert(pool_id, &caller, staker); Ok(()) } diff --git a/substrate/frame/staking-rewards/src/tests.rs b/substrate/frame/staking-rewards/src/tests.rs index 1494f1c776b4..ddcc8b5d2967 100644 --- a/substrate/frame/staking-rewards/src/tests.rs +++ b/substrate/frame/staking-rewards/src/tests.rs @@ -55,6 +55,8 @@ fn pools() -> Vec<(u32, PoolInfo, u128, u64>)> { } mod create_pool { + use sp_runtime::traits::BadOrigin; + use super::*; #[test] @@ -168,7 +170,7 @@ mod create_pool { } #[test] - fn non_existent_asset_fails() { + fn fails_for_non_existent_asset() { new_test_ext().execute_with(|| { let valid_asset = NativeOrWithId::::WithId(1); let invalid_asset = NativeOrWithId::::WithId(200); @@ -207,6 +209,27 @@ mod create_pool { ); }) } + + #[test] + fn fails_for_not_admin() { + new_test_ext().execute_with(|| { + let user = 100; + let staking_asset_id = NativeOrWithId::::Native; + let reward_asset_id = NativeOrWithId::::WithId(1); + let reward_rate_per_block = 100; + create_tokens(user, vec![reward_asset_id.clone()]); + assert_err!( + StakingRewards::create_pool( + RuntimeOrigin::signed(user), + Box::new(staking_asset_id.clone()), + Box::new(reward_asset_id.clone()), + reward_rate_per_block, + Some(999) + ), + BadOrigin + ); + }); + } } mod stake { @@ -220,7 +243,6 @@ mod stake { let staking_asset_id = NativeOrWithId::::WithId(1); let reward_asset_id = NativeOrWithId::::Native; let reward_rate_per_block = 100; - create_tokens(user, vec![staking_asset_id.clone()]); assert_ok!(StakingRewards::create_pool( @@ -258,17 +280,14 @@ mod stake { } #[test] - fn non_existent_pool() { + fn fails_for_non_existent_pool() { new_test_ext().execute_with(|| { - // Setup let user = 1; let staking_asset_id = NativeOrWithId::::WithId(1); - create_tokens(user, vec![staking_asset_id.clone()]); let non_existent_pool_id = 999; - // User tries to stake tokens in a non-existent pool assert_err!( StakingRewards::stake(RuntimeOrigin::signed(user), non_existent_pool_id, 1000), Error::::NonExistentPool @@ -277,7 +296,101 @@ mod stake { } #[test] - fn insufficient_balance() { + fn fails_for_insufficient_balance() { // TODO: When we're able to freeze assets. } } + +mod unstake { + use super::*; + + #[test] + fn success() { + new_test_ext().execute_with(|| { + // Setup + let user = 1; + let staking_asset_id = NativeOrWithId::::WithId(1); + let reward_asset_id = NativeOrWithId::::WithId(2); + let reward_rate_per_block = 100; + create_tokens(user, vec![staking_asset_id.clone(), reward_asset_id.clone()]); + + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::signed(user), + Box::new(staking_asset_id.clone()), + Box::new(reward_asset_id.clone()), + reward_rate_per_block, + None + )); + + let pool_id = 0; + + // User stakes tokens + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(user), pool_id, 1000)); + + // User unstakes tokens + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(user), pool_id, 500)); + + // Check that the user's staked amount is updated + assert_eq!(PoolStakers::::get(pool_id, user).unwrap().amount, 500); + + // Check that the pool's total tokens staked is updated + assert_eq!(Pools::::get(pool_id).unwrap().total_tokens_staked, 500); + + // User unstakes remaining tokens + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(user), pool_id, 500)); + + // Check that the user's staked amount is zero + assert_eq!(PoolStakers::::get(pool_id, user).unwrap().amount, 0); + + // Check that the pool's total tokens staked is zero + assert_eq!(Pools::::get(pool_id).unwrap().total_tokens_staked, 0); + }); + } + + #[test] + fn fails_for_non_existent_pool() { + new_test_ext().execute_with(|| { + // Setup + let user = 1; + let non_existent_pool_id = 999; + + // User tries to unstake tokens from a non-existent pool + assert_err!( + StakingRewards::unstake(RuntimeOrigin::signed(user), non_existent_pool_id, 500), + Error::::NonExistentPool + ); + }); + } + + #[test] + fn fails_for_insufficient_staked_amount() { + new_test_ext().execute_with(|| { + // Setup + let user = 1; + let staking_asset_id = NativeOrWithId::::WithId(1); + let reward_asset_id = NativeOrWithId::::WithId(2); + let reward_rate_per_block = 100; + + create_tokens(user, vec![staking_asset_id.clone(), reward_asset_id.clone()]); + + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::signed(user), + Box::new(staking_asset_id.clone()), + Box::new(reward_asset_id.clone()), + reward_rate_per_block, + None + )); + + let pool_id = 0; + + // User stakes tokens + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(user), pool_id, 1000)); + + // User tries to unstake more tokens than they have staked + assert_err!( + StakingRewards::unstake(RuntimeOrigin::signed(user), pool_id, 1500), + Error::::NotEnoughTokens + ); + }); + } +} From 60191d506b080a3c49076ab574c9afc4d488751b Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Mon, 1 Apr 2024 17:26:40 +0400 Subject: [PATCH 011/159] rename pallet-asset-rewards --- Cargo.lock | 40 +++++++++---------- Cargo.toml | 2 +- .../Cargo.toml | 2 +- .../src/lib.rs | 0 .../src/mock.rs | 0 .../src/tests.rs | 0 6 files changed, 22 insertions(+), 22 deletions(-) rename substrate/frame/{staking-rewards => asset-rewards}/Cargo.toml (98%) rename substrate/frame/{staking-rewards => asset-rewards}/src/lib.rs (100%) rename substrate/frame/{staking-rewards => asset-rewards}/src/mock.rs (100%) rename substrate/frame/{staking-rewards => asset-rewards}/src/tests.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index b03407f8f275..7dc7f8d8e75e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9078,6 +9078,26 @@ dependencies = [ "sp-std 14.0.0", ] +[[package]] +name = "pallet-asset-rewards" +version = "1.0.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-assets", + "pallet-balances", + "parity-scale-codec", + "primitive-types", + "scale-info", + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 14.0.0", +] + [[package]] name = "pallet-asset-tx-payment" version = "28.0.0" @@ -10869,26 +10889,6 @@ dependencies = [ "sp-arithmetic", ] -[[package]] -name = "pallet-staking-rewards" -version = "1.0.0" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "pallet-assets", - "pallet-balances", - "parity-scale-codec", - "primitive-types", - "scale-info", - "sp-api", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std 14.0.0", -] - [[package]] name = "pallet-staking-runtime-api" version = "14.0.0" diff --git a/Cargo.toml b/Cargo.toml index cf5081232940..e8590b09b990 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -381,7 +381,7 @@ members = [ "substrate/frame/session/benchmarking", "substrate/frame/society", "substrate/frame/staking", - "substrate/frame/staking-rewards", + "substrate/frame/asset-rewards", "substrate/frame/staking/reward-curve", "substrate/frame/staking/reward-fn", "substrate/frame/staking/runtime-api", diff --git a/substrate/frame/staking-rewards/Cargo.toml b/substrate/frame/asset-rewards/Cargo.toml similarity index 98% rename from substrate/frame/staking-rewards/Cargo.toml rename to substrate/frame/asset-rewards/Cargo.toml index 0a693545f764..346af2f6ffa3 100644 --- a/substrate/frame/staking-rewards/Cargo.toml +++ b/substrate/frame/asset-rewards/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pallet-staking-rewards" +name = "pallet-asset-rewards" version = "1.0.0" authors.workspace = true edition.workspace = true diff --git a/substrate/frame/staking-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs similarity index 100% rename from substrate/frame/staking-rewards/src/lib.rs rename to substrate/frame/asset-rewards/src/lib.rs diff --git a/substrate/frame/staking-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs similarity index 100% rename from substrate/frame/staking-rewards/src/mock.rs rename to substrate/frame/asset-rewards/src/mock.rs diff --git a/substrate/frame/staking-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs similarity index 100% rename from substrate/frame/staking-rewards/src/tests.rs rename to substrate/frame/asset-rewards/src/tests.rs From 31a3c89dd19e0984fd2e144a1e57d20246452121 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Mon, 1 Apr 2024 17:45:41 +0400 Subject: [PATCH 012/159] stake unstake events --- substrate/frame/asset-rewards/src/lib.rs | 53 +++++++++++++++++----- substrate/frame/asset-rewards/src/tests.rs | 18 ++++++++ 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 1883b1dffba0..c582ca3bf054 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -118,7 +118,7 @@ pub mod pallet { traits::tokens::{AssetId, Preservation}, }; use frame_system::pallet_prelude::*; - use sp_runtime::traits::{AccountIdConversion, EnsureDiv, Saturating}; + use sp_runtime::traits::{AccountIdConversion, BadOrigin, EnsureDiv, Saturating}; #[pallet::pallet] pub struct Pallet(_); @@ -228,11 +228,13 @@ pub mod pallet { pool_id: PoolId, }, /// A pool was modified by the admin. - PoolModifed { + PoolModified { /// The modified pool. pool_id: PoolId, - /// The new reward rate. - new_reward_rate_per_block: T::Balance, + /// The reward rate after the modification. + new_reward_rate_per_block: Option, + /// The admin after the modification. + new_admin: Option, }, } @@ -345,6 +347,9 @@ pub mod pallet { staker.amount.saturating_accrue(amount); PoolStakers::::insert(pool_id, &caller, staker); + // Emit event. + Self::deposit_event(Event::Staked { who: caller, pool_id, amount }); + Ok(()) } @@ -375,6 +380,9 @@ pub mod pallet { staker.amount.saturating_reduce(amount); PoolStakers::::insert(pool_id, &caller, staker); + // Emit event. + Self::deposit_event(Event::Unstaked { who: caller, pool_id, amount }); + Ok(()) } @@ -398,7 +406,6 @@ pub mod pallet { let mut staker_info = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; let pool_account_id = Self::pool_account_id(&pool_id)?; - T::Assets::transfer( pool_info.reward_asset_id, &pool_account_id, @@ -407,19 +414,43 @@ pub mod pallet { Preservation::Preserve, )?; - // Reset staker unclaimed rewards. + // Emit event. + Self::deposit_event(Event::RewardsHarvested { + who: caller, + staker, + pool_id, + amount: staker_info.rewards, + }); + + // Reset staker rewards. staker_info.rewards = 0u32.into(); Ok(()) } - /// Modify the reward rate of a pool. + /// Modify the parameters of a pool. pub fn modify_pool( - _origin: OriginFor, - _pool_id: PoolId, - _new_reward_rate: T::Balance, + origin: OriginFor, + pool_id: PoolId, + new_reward_rate_per_block: Option, + new_admin: Option, ) -> DispatchResult { - todo!() + let caller = ensure_signed(origin)?; + + let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + ensure!(pool_info.admin == caller, BadOrigin); + pool_info.reward_rate_per_block = + new_reward_rate_per_block.unwrap_or(pool_info.reward_rate_per_block); + pool_info.admin = new_admin.clone().unwrap_or(pool_info.admin); + Pools::::insert(pool_id, pool_info); + + Self::deposit_event(Event::PoolModified { + pool_id, + new_reward_rate_per_block, + new_admin, + }); + + Ok(()) } /// Convinience method to deposit reward tokens into a pool. diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index ddcc8b5d2967..3e28f25f316c 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -261,6 +261,12 @@ mod stake { // Check that the user's staked amount is updated assert_eq!(PoolStakers::::get(pool_id, user).unwrap().amount, 1000); + // Event is emitted. + assert_eq!( + *events().last().unwrap(), + Event::::Staked { who: user, amount: 1000, pool_id: 0 } + ); + // Check that the pool's total tokens staked is updated assert_eq!(Pools::::get(pool_id).unwrap().total_tokens_staked, 1000); @@ -269,6 +275,12 @@ mod stake { // User stakes more tokens assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(user), pool_id, 500)); + // Event is emitted. + assert_eq!( + *events().last().unwrap(), + Event::::Staked { who: user, amount: 500, pool_id: 0 } + ); + // Check that the user's staked amount is updated assert_eq!(PoolStakers::::get(pool_id, user).unwrap().amount, 1500); @@ -330,6 +342,12 @@ mod unstake { // User unstakes tokens assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(user), pool_id, 500)); + // Event is emitted. + assert_eq!( + *events().last().unwrap(), + Event::::Unstaked { who: user, amount: 500, pool_id: 0 } + ); + // Check that the user's staked amount is updated assert_eq!(PoolStakers::::get(pool_id, user).unwrap().amount, 500); From 7a15551171fdd794afe5b38a503668c9c940029d Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 2 Apr 2024 11:01:01 +0400 Subject: [PATCH 013/159] add integration test --- substrate/frame/asset-rewards/Cargo.toml | 2 +- substrate/frame/asset-rewards/src/lib.rs | 36 +++--- substrate/frame/asset-rewards/src/mock.rs | 2 +- substrate/frame/asset-rewards/src/tests.rs | 142 ++++++++++++++++++++- 4 files changed, 157 insertions(+), 25 deletions(-) diff --git a/substrate/frame/asset-rewards/Cargo.toml b/substrate/frame/asset-rewards/Cargo.toml index 346af2f6ffa3..b0ef2c2199eb 100644 --- a/substrate/frame/asset-rewards/Cargo.toml +++ b/substrate/frame/asset-rewards/Cargo.toml @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } -frame-support = { path = "../support", default-features = false } +frame-support = { path = "../support", default-features = false, features = ["experimental"] } frame-system = { path = "../system", default-features = false } frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index c582ca3bf054..ef7187188ed1 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -80,7 +80,7 @@ pub type PoolId = u32; pub(crate) const PRECISION_SCALING_FACTOR: u32 = u32::MAX; /// A pool staker. -#[derive(Default, Decode, Encode, MaxEncodedLen, TypeInfo)] +#[derive(Debug, Default, Decode, Encode, MaxEncodedLen, TypeInfo)] pub struct PoolStakerInfo { /// Amount of tokens staked. amount: Balance, @@ -416,7 +416,7 @@ pub mod pallet { // Emit event. Self::deposit_event(Event::RewardsHarvested { - who: caller, + who: caller.clone(), staker, pool_id, amount: staker_info.rewards, @@ -424,6 +424,7 @@ pub mod pallet { // Reset staker rewards. staker_info.rewards = 0u32.into(); + PoolStakers::::insert(pool_id, &caller, staker_info); Ok(()) } @@ -479,7 +480,7 @@ pub mod pallet { impl Pallet { /// Derive a pool account ID from the pallet's ID. - fn pool_account_id(id: &PoolId) -> Result { + pub fn pool_account_id(id: &PoolId) -> Result { if Pools::::contains_key(id) { Ok(T::PalletId::get().into_sub_account_truncating(id)) } else { @@ -488,18 +489,19 @@ pub mod pallet { } /// Update pool reward state. - fn update_pool_rewards(pool_id: &PoolId, staker: &T::AccountId) -> DispatchResult { + pub fn update_pool_rewards(pool_id: &PoolId, staker: &T::AccountId) -> DispatchResult { let reward_per_token = Self::reward_per_token(pool_id)?; - let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - pool_info.last_update_block = frame_system::Pallet::::block_number(); - Pools::::insert(pool_id, pool_info); - let mut staker_info = PoolStakers::::get(pool_id, staker).unwrap_or_default(); staker_info.rewards = Self::derive_rewards(pool_id, staker)?; staker_info.reward_per_token_paid = reward_per_token; PoolStakers::::insert(pool_id, staker, staker_info); + let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + pool_info.last_update_block = frame_system::Pallet::::block_number(); + pool_info.reward_per_token_stored = reward_per_token; + Pools::::insert(pool_id, pool_info); + Ok(()) } @@ -510,7 +512,7 @@ pub mod pallet { let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; if pool_info.total_tokens_staked.eq(&0u32.into()) { - return Ok(0u32.into()); + return Ok(pool_info.reward_per_token_stored) } let blocks_elapsed: u32 = match frame_system::Pallet::::block_number() @@ -521,15 +523,13 @@ pub mod pallet { Err(_) => return Err(Error::::BlockNumberConversionError.into()), }; - Ok(pool_info - .reward_per_token_stored - .saturating_add( - pool_info - .reward_rate_per_block - .saturating_mul(blocks_elapsed.into()) - .saturating_mul(PRECISION_SCALING_FACTOR.into()), - ) - .ensure_div(pool_info.total_tokens_staked)?) + Ok(pool_info.reward_per_token_stored.saturating_add( + pool_info + .reward_rate_per_block + .saturating_mul(blocks_elapsed.into()) + .saturating_mul(PRECISION_SCALING_FACTOR.into()) + .ensure_div(pool_info.total_tokens_staked)?, + )) } /// Derives the amount of rewards earned by a staker. diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index 658d1bb68426..c179f0863dad 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -157,7 +157,7 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities { // .unwrap(); pallet_balances::GenesisConfig:: { - balances: vec![(1, 10000), (2, 20000), (3, 30000), (4, 40000)], + balances: vec![(1, 10000), (2, 20000), (3, 30000), (4, 40000), (10, 40000), (20, 40000)], } .assimilate_storage(&mut t) .unwrap(); diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 3e28f25f316c..cf459e5af06b 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -16,13 +16,10 @@ // limitations under the License. use crate::{mock::*, *}; -use frame_support::{assert_err, assert_ok, traits::fungible::NativeOrWithId}; +use frame_support::{assert_err, assert_ok, hypothetically, traits::fungible::NativeOrWithId}; fn create_tokens(owner: u128, tokens: Vec>) { - create_tokens_with_ed(owner, tokens, 1) -} - -fn create_tokens_with_ed(owner: u128, tokens: Vec>, ed: u128) { + let ed = 1; for token_id in tokens { let asset_id = match token_id { NativeOrWithId::WithId(id) => id, @@ -412,3 +409,138 @@ mod unstake { }); } } + +mod integration { + use super::*; + + /// Assert that an amount has been hypothetically earned by a staker. + fn assert_hypothetically_earned( + staker: u128, + expected_earned: u128, + pool_id: u32, + reward_asset_id: NativeOrWithId, + ) { + hypothetically!({ + // Get the pre-harvest balance. + let balance_before: ::Balance = + <::Assets>::balance(reward_asset_id.clone(), &staker); + + // Harvest the rewards. + assert_ok!(StakingRewards::harvest_rewards( + RuntimeOrigin::signed(staker), + pool_id, + None + )); + + // Sanity check: staker rewards are reset to 0. + assert_eq!(PoolStakers::::get(pool_id, staker).unwrap().rewards, 0); + + // Check that the staker has earned the expected amount. + let balance_after = + <::Assets>::balance(reward_asset_id.clone(), &staker); + assert_eq!( + balance_after - balance_before, + ::Balance>>::into(expected_earned) + ); + }); + } + + #[test] + /// In this integration test scenario, we will consider 2 stakers each staking and unstaking at + /// different intervals, and assert their claimable rewards are as expected. + /// + /// Note: There are occasionally off by 1 errors due to rounding. In practice, this is + /// insignificant. + fn two_stakers() { + new_test_ext().execute_with(|| { + // Setup + let admin = 1; + let staker1 = 10u128; + let staker2 = 20; + let staking_asset_id = NativeOrWithId::::WithId(1); + let reward_asset_id = NativeOrWithId::::Native; + let reward_rate_per_block = 100; + create_tokens(admin, vec![staking_asset_id.clone()]); + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::signed(admin), + Box::new(staking_asset_id.clone()), + Box::new(reward_asset_id.clone()), + reward_rate_per_block, + None + )); + let pool_id = 0; + let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); + <::Assets>::set_balance( + reward_asset_id.clone(), + &pool_account_id, + 100_000, + ); + <::Assets>::set_balance( + staking_asset_id.clone(), + &staker1, + 100_000, + ); + <::Assets>::set_balance( + staking_asset_id.clone(), + &staker2, + 100_000, + ); + + // Block 7: Staker 1 stakes 100 tokens. + System::set_block_number(7); + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker1), pool_id, 100)); + // At this point + // - Staker 1 has earned 0 tokens. + // - Staker 1 is earning 100 tokens per block. + + // Check that Staker 1 has earned 0 tokens. + assert_hypothetically_earned(staker1, 0, pool_id, reward_asset_id.clone()); + + // Block 9: Staker 2 stakes 100 tokens. + System::set_block_number(9); + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker2), pool_id, 100)); + // At this point + // - Staker 1 has earned 200 (100*2) tokens. + // - Staker 2 has earned 0 tokens. + // - Staker 1 is earning 50 tokens per block. + // - Staker 2 is earning 50 tokens per block. + + // Check that Staker 1 has earned 200 tokens and Staker 2 has earned 0 tokens. + assert_hypothetically_earned(staker1, 200, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 0, pool_id, reward_asset_id.clone()); + + // Block 12: Staker 1 stakes an additional 100 tokens. + System::set_block_number(12); + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker1), pool_id, 100)); + // At this point + // - Staker 1 has earned 350 (200 + (50 * 3)) tokens. + // - Staker 2 has earned 150 (50 * 3) tokens. + // - Staker 1 is earning 66.66 tokens per block. + // - Staker 2 is earning 33.33 tokens per block. + + // Check that Staker 1 has earned 350 tokens and Staker 2 has earned 150 tokens. + assert_hypothetically_earned(staker1, 349, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 149, pool_id, reward_asset_id.clone()); + + // Block 22: Staker 1 unstakes 100 tokens. + System::set_block_number(22); + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker1), pool_id, 100)); + // - Staker 1 has earned 1016 (350 + 66.66 * 10) tokens. + // - Staker 2 has earned 483 (150 + 33.33 * 10) tokens. + // - Staker 1 is earning 50 tokens per block. + // - Staker 2 is earning 50 tokens per block. + assert_hypothetically_earned(staker1, 1015, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 483, pool_id, reward_asset_id.clone()); + + // Block 23: Staker 1 unstakes 100 tokens. + System::set_block_number(23); + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker1), pool_id, 100)); + // - Staker 1 has earned 1065 (1015 + 50) tokens. + // - Staker 2 has earned 533 (483 + 50) tokens. + // - Staker 1 is earning 0 tokens per block. + // - Staker 2 is earning 100 tokens per block. + assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 533, pool_id, reward_asset_id.clone()); + }); + } +} From 3742869968224dc73a7015b4512e30a9b45f716d Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 2 Apr 2024 16:32:31 +0400 Subject: [PATCH 014/159] add expiry block and improve pool admin calls --- substrate/frame/asset-rewards/src/lib.rs | 125 +++++++--- substrate/frame/asset-rewards/src/tests.rs | 257 +++++++++++++++++---- 2 files changed, 310 insertions(+), 72 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index ef7187188ed1..afb91f421705 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -105,6 +105,8 @@ pub struct PoolInfo { reward_per_token_stored: Balance, /// Last block number the pool was updated. Used when calculating payouts. last_update_block: BlockNumber, + /// The block the pool will cease distributing rewards. + expiry_block: BlockNumber, /// Permissioned account that can manage this pool. admin: AccountId, } @@ -219,6 +221,8 @@ pub mod pallet { reward_asset_id: T::AssetId, /// The initial reward rate per block. reward_rate_per_block: T::Balance, + /// The block the pool will cease to accumulate rewards. + expiry_block: BlockNumberFor, /// The account allowed to modify the pool. admin: T::AccountId, }, @@ -227,14 +231,26 @@ pub mod pallet { /// The deleted pool id. pool_id: PoolId, }, - /// A pool was modified by the admin. - PoolModified { + /// A pool reward rate was modified by the admin. + PoolRewardRateModified { /// The modified pool. pool_id: PoolId, - /// The reward rate after the modification. - new_reward_rate_per_block: Option, - /// The admin after the modification. - new_admin: Option, + /// The new reward rate per block. + new_reward_rate_per_block: T::Balance, + }, + /// A pool admin modified by the admin. + PoolAdminModified { + /// The modified pool. + pool_id: PoolId, + /// The new admin. + new_admin: T::AccountId, + }, + /// A pool expiry block was modified by the admin. + PoolExpiryBlockModified { + /// The modified pool. + pool_id: PoolId, + /// The new expiry block. + new_expiry_block: BlockNumberFor, }, } @@ -248,6 +264,8 @@ pub mod pallet { NonExistentAsset, /// There was an error converting a block number. BlockNumberConversionError, + /// Expiry block must be in the future. + ExpiryBlockMustBeInTheFuture, } #[pallet::hooks] @@ -269,6 +287,7 @@ pub mod pallet { staked_asset_id: Box, reward_asset_id: Box, reward_rate_per_block: T::Balance, + expiry_block: BlockNumberFor, admin: Option, ) -> DispatchResult { // Ensure Origin is allowed to create pools. @@ -284,6 +303,12 @@ pub mod pallet { Error::::NonExistentAsset ); + // Check the expiry block. + ensure!( + expiry_block > frame_system::Pallet::::block_number(), + Error::::ExpiryBlockMustBeInTheFuture + ); + // Get the admin, defaulting to the origin. let origin_acc_id = ensure_signed(origin)?; let admin = match admin { @@ -299,6 +324,7 @@ pub mod pallet { total_tokens_staked: 0u32.into(), reward_per_token_stored: 0u32.into(), last_update_block: 0u32.into(), + expiry_block, admin: admin.clone(), }; @@ -314,6 +340,7 @@ pub mod pallet { staking_asset_id: *staked_asset_id, reward_asset_id: *reward_asset_id, reward_rate_per_block, + expiry_block, admin, }); @@ -332,7 +359,7 @@ pub mod pallet { let caller = ensure_signed(origin)?; // Always start by updating the pool rewards. - Self::update_pool_rewards(&pool_id, &caller)?; + Self::update_pool_rewards(&pool_id, Some(&caller))?; // Try to freeze the staker assets. // TODO: (blocked https://github.com/paritytech/polkadot-sdk/issues/3342) @@ -362,7 +389,7 @@ pub mod pallet { let caller = ensure_signed(origin)?; // Always start by updating the pool rewards. - Self::update_pool_rewards(&pool_id, &caller)?; + Self::update_pool_rewards(&pool_id, Some(&caller))?; // Check the staker has enough staked tokens. let mut staker = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); @@ -400,7 +427,7 @@ pub mod pallet { }; // Always start by updating the pool rewards. - Self::update_pool_rewards(&pool_id, &staker)?; + Self::update_pool_rewards(&pool_id, Some(&staker))?; // Transfer unclaimed rewards from the pool to the staker. let mut staker_info = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); @@ -429,31 +456,72 @@ pub mod pallet { Ok(()) } - /// Modify the parameters of a pool. - pub fn modify_pool( + /// Modify a pool reward rate. + pub fn set_pool_reward_rate_per_block( origin: OriginFor, pool_id: PoolId, - new_reward_rate_per_block: Option, - new_admin: Option, + new_reward_rate_per_block: T::Balance, ) -> DispatchResult { let caller = ensure_signed(origin)?; - let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; ensure!(pool_info.admin == caller, BadOrigin); - pool_info.reward_rate_per_block = - new_reward_rate_per_block.unwrap_or(pool_info.reward_rate_per_block); - pool_info.admin = new_admin.clone().unwrap_or(pool_info.admin); + + Self::update_pool_rewards(&pool_id, None)?; + + pool_info.reward_rate_per_block = new_reward_rate_per_block; Pools::::insert(pool_id, pool_info); - Self::deposit_event(Event::PoolModified { + Self::deposit_event(Event::PoolRewardRateModified { pool_id, new_reward_rate_per_block, - new_admin, }); Ok(()) } + /// Modify a pool admin. + pub fn set_pool_admin( + origin: OriginFor, + pool_id: PoolId, + new_admin: T::AccountId, + ) -> DispatchResult { + let caller = ensure_signed(origin)?; + + let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + ensure!(pool_info.admin == caller, BadOrigin); + pool_info.admin = new_admin.clone(); + Pools::::insert(pool_id, pool_info); + + Self::deposit_event(Event::PoolAdminModified { pool_id, new_admin }); + + Ok(()) + } + + /// Modify a pool admin. + /// + /// TODO: Actually handle this in code + pub fn set_pool_expiry_block( + origin: OriginFor, + pool_id: PoolId, + new_expiry_block: BlockNumberFor, + ) -> DispatchResult { + let caller = ensure_signed(origin)?; + + ensure!( + new_expiry_block > frame_system::Pallet::::block_number(), + Error::::ExpiryBlockMustBeInTheFuture + ); + + let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + ensure!(pool_info.admin == caller, BadOrigin); + pool_info.expiry_block = new_expiry_block; + Pools::::insert(pool_id, pool_info); + + Self::deposit_event(Event::PoolExpiryBlockModified { pool_id, new_expiry_block }); + + Ok(()) + } + /// Convinience method to deposit reward tokens into a pool. /// /// This method is not strictly necessary (tokens could be transferred directly to the @@ -488,20 +556,25 @@ pub mod pallet { } } - /// Update pool reward state. - pub fn update_pool_rewards(pool_id: &PoolId, staker: &T::AccountId) -> DispatchResult { + /// Update pool reward state, and optionally also a staker's rewards. + pub fn update_pool_rewards( + pool_id: &PoolId, + staker: Option<&T::AccountId>, + ) -> DispatchResult { let reward_per_token = Self::reward_per_token(pool_id)?; - let mut staker_info = PoolStakers::::get(pool_id, staker).unwrap_or_default(); - staker_info.rewards = Self::derive_rewards(pool_id, staker)?; - staker_info.reward_per_token_paid = reward_per_token; - PoolStakers::::insert(pool_id, staker, staker_info); - let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; pool_info.last_update_block = frame_system::Pallet::::block_number(); pool_info.reward_per_token_stored = reward_per_token; Pools::::insert(pool_id, pool_info); + if let Some(staker) = staker { + let mut staker_info = PoolStakers::::get(pool_id, staker).unwrap_or_default(); + staker_info.rewards = Self::derive_rewards(pool_id, staker)?; + staker_info.reward_per_token_paid = reward_per_token; + PoolStakers::::insert(pool_id, staker, staker_info); + } + Ok(()) } diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index cf459e5af06b..0e1f9e921c6d 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -17,6 +17,28 @@ use crate::{mock::*, *}; use frame_support::{assert_err, assert_ok, hypothetically, traits::fungible::NativeOrWithId}; +use sp_runtime::traits::BadOrigin; + +/// Creates a basic pool with values: +/// - Staking asset: 1 +/// - Reward asset: Native +/// - Reward rate per block: 100 +/// - Expiry block: 100 +/// - Admin: 1 +/// +/// Useful for tests when you don't care about customising, or reusing the pool params. +fn create_default_pool() { + let staking_asset_id = NativeOrWithId::::WithId(1); + create_tokens(1, vec![staking_asset_id.clone()]); + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::signed(1), + Box::new(staking_asset_id), + Box::new(NativeOrWithId::::Native), + 100, + 100u64, + None + )); +} fn create_tokens(owner: u128, tokens: Vec>) { let ed = 1; @@ -52,8 +74,6 @@ fn pools() -> Vec<(u32, PoolInfo, u128, u64>)> { } mod create_pool { - use sp_runtime::traits::BadOrigin; - use super::*; #[test] @@ -64,17 +84,19 @@ mod create_pool { let staking_asset_id = NativeOrWithId::::Native; let reward_asset_id = NativeOrWithId::::WithId(1); let reward_rate_per_block = 100; + let expiry_block = 200u64; create_tokens(user, vec![reward_asset_id.clone()]); - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), user, 1000)); // Create a pool with default admin. assert_eq!(NextPoolId::::get(), 0); + assert_ok!(StakingRewards::create_pool( RuntimeOrigin::signed(user), Box::new(staking_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, + expiry_block, None )); @@ -87,6 +109,7 @@ mod create_pool { staking_asset_id: staking_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, + expiry_block, admin: user, }] ); @@ -101,6 +124,7 @@ mod create_pool { staking_asset_id: staking_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, + expiry_block, admin: user, total_tokens_staked: 0, reward_per_token_stored: 0, @@ -116,6 +140,7 @@ mod create_pool { Box::new(staking_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, + expiry_block, Some(admin) )); @@ -129,6 +154,7 @@ mod create_pool { reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, admin, + expiry_block, }] ); @@ -144,6 +170,7 @@ mod create_pool { reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, admin: user, + expiry_block, total_tokens_staked: 0, reward_per_token_stored: 0, last_update_block: 0 @@ -157,6 +184,7 @@ mod create_pool { reward_rate_per_block, admin, total_tokens_staked: 0, + expiry_block, reward_per_token_stored: 0, last_update_block: 0 } @@ -178,6 +206,7 @@ mod create_pool { Box::new(valid_asset.clone()), Box::new(invalid_asset.clone()), 10, + 10u64, None ), Error::::NonExistentAsset @@ -189,6 +218,7 @@ mod create_pool { Box::new(invalid_asset.clone()), Box::new(valid_asset.clone()), 10, + 10u64, None ), Error::::NonExistentAsset @@ -200,6 +230,7 @@ mod create_pool { Box::new(invalid_asset.clone()), Box::new(invalid_asset.clone()), 10, + 10u64, None ), Error::::NonExistentAsset @@ -214,6 +245,7 @@ mod create_pool { let staking_asset_id = NativeOrWithId::::Native; let reward_asset_id = NativeOrWithId::::WithId(1); let reward_rate_per_block = 100; + let expiry_block = 100u64; create_tokens(user, vec![reward_asset_id.clone()]); assert_err!( StakingRewards::create_pool( @@ -221,12 +253,37 @@ mod create_pool { Box::new(staking_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, + expiry_block, Some(999) ), BadOrigin ); }); } + + #[test] + fn fails_for_bad_expiry_block() { + new_test_ext().execute_with(|| { + let user = 1; + let staking_asset_id = NativeOrWithId::::Native; + let reward_asset_id = NativeOrWithId::::WithId(1); + let reward_rate_per_block = 100; + let expiry_block = 100u64; + create_tokens(user, vec![reward_asset_id.clone()]); + System::set_block_number(expiry_block + 1u64); + assert_err!( + StakingRewards::create_pool( + RuntimeOrigin::signed(user), + Box::new(staking_asset_id.clone()), + Box::new(reward_asset_id.clone()), + reward_rate_per_block, + expiry_block, + None + ), + Error::::ExpiryBlockMustBeInTheFuture + ); + }); + } } mod stake { @@ -235,21 +292,8 @@ mod stake { #[test] fn success() { new_test_ext().execute_with(|| { - // Setup let user = 1; - let staking_asset_id = NativeOrWithId::::WithId(1); - let reward_asset_id = NativeOrWithId::::Native; - let reward_rate_per_block = 100; - create_tokens(user, vec![staking_asset_id.clone()]); - - assert_ok!(StakingRewards::create_pool( - RuntimeOrigin::signed(user), - Box::new(staking_asset_id.clone()), - Box::new(reward_asset_id.clone()), - reward_rate_per_block, - None - )); - + create_default_pool(); let pool_id = 0; // User stakes tokens @@ -316,21 +360,8 @@ mod unstake { #[test] fn success() { new_test_ext().execute_with(|| { - // Setup let user = 1; - let staking_asset_id = NativeOrWithId::::WithId(1); - let reward_asset_id = NativeOrWithId::::WithId(2); - let reward_rate_per_block = 100; - create_tokens(user, vec![staking_asset_id.clone(), reward_asset_id.clone()]); - - assert_ok!(StakingRewards::create_pool( - RuntimeOrigin::signed(user), - Box::new(staking_asset_id.clone()), - Box::new(reward_asset_id.clone()), - reward_rate_per_block, - None - )); - + create_default_pool(); let pool_id = 0; // User stakes tokens @@ -380,22 +411,8 @@ mod unstake { #[test] fn fails_for_insufficient_staked_amount() { new_test_ext().execute_with(|| { - // Setup let user = 1; - let staking_asset_id = NativeOrWithId::::WithId(1); - let reward_asset_id = NativeOrWithId::::WithId(2); - let reward_rate_per_block = 100; - - create_tokens(user, vec![staking_asset_id.clone(), reward_asset_id.clone()]); - - assert_ok!(StakingRewards::create_pool( - RuntimeOrigin::signed(user), - Box::new(staking_asset_id.clone()), - Box::new(reward_asset_id.clone()), - reward_rate_per_block, - None - )); - + create_default_pool(); let pool_id = 0; // User stakes tokens @@ -410,6 +427,152 @@ mod unstake { } } +mod set_pool_admin { + use super::*; + + #[test] + fn success() { + new_test_ext().execute_with(|| { + let admin = 1; + let new_admin = 2; + let pool_id = 0; + create_default_pool(); + + // Modify the pool admin + assert_ok!(StakingRewards::set_pool_admin( + RuntimeOrigin::signed(admin), + pool_id, + new_admin + )); + + // Check state + assert_eq!( + *events().last().unwrap(), + Event::::PoolAdminModified { pool_id, new_admin } + ); + assert_eq!(Pools::::get(pool_id).unwrap().admin, new_admin); + }); + } + + #[test] + fn fails_for_non_existent_pool() { + new_test_ext().execute_with(|| { + let admin = 1; + let new_admin = 2; + let non_existent_pool_id = 999; + + assert_err!( + StakingRewards::set_pool_admin( + RuntimeOrigin::signed(admin), + non_existent_pool_id, + new_admin + ), + Error::::NonExistentPool + ); + }); + } + + #[test] + fn fails_for_non_admin() { + new_test_ext().execute_with(|| { + let new_admin = 2; + let non_admin = 3; + let pool_id = 0; + create_default_pool(); + + assert_err!( + StakingRewards::set_pool_admin( + RuntimeOrigin::signed(non_admin), + pool_id, + new_admin + ), + BadOrigin + ); + }); + } +} + +mod set_pool_expiry_block { + use super::*; + + #[test] + fn success() { + new_test_ext().execute_with(|| { + let admin = 1; + let pool_id = 0; + let new_expiry_block = 200u64; + create_default_pool(); + + // Modify the pool expiry block + assert_ok!(StakingRewards::set_pool_expiry_block( + RuntimeOrigin::signed(admin), + pool_id, + new_expiry_block + )); + + // Check state + assert_eq!( + *events().last().unwrap(), + Event::::PoolExpiryBlockModified { pool_id, new_expiry_block } + ); + assert_eq!(Pools::::get(pool_id).unwrap().expiry_block, new_expiry_block); + }); + } + + #[test] + fn fails_for_non_existent_pool() { + new_test_ext().execute_with(|| { + let admin = 1; + let non_existent_pool_id = 999; + let new_expiry_block = 200u64; + + assert_err!( + StakingRewards::set_pool_expiry_block( + RuntimeOrigin::signed(admin), + non_existent_pool_id, + new_expiry_block + ), + Error::::NonExistentPool + ); + }); + } + + #[test] + fn fails_for_non_admin() { + new_test_ext().execute_with(|| { + let non_admin = 2; + let pool_id = 0; + let new_expiry_block = 200u64; + create_default_pool(); + + assert_err!( + StakingRewards::set_pool_expiry_block( + RuntimeOrigin::signed(non_admin), + pool_id, + new_expiry_block + ), + BadOrigin + ); + }); + } + + #[test] + fn fails_for_expiry_block_in_the_past() { + new_test_ext().execute_with(|| { + let admin = 1; + let pool_id = 0; + create_default_pool(); + + System::set_block_number(5000); + + assert_err!( + StakingRewards::set_pool_expiry_block(RuntimeOrigin::signed(admin), pool_id, 2u64), + Error::::ExpiryBlockMustBeInTheFuture + ); + }); + } +} + mod integration { use super::*; @@ -460,12 +623,14 @@ mod integration { let staking_asset_id = NativeOrWithId::::WithId(1); let reward_asset_id = NativeOrWithId::::Native; let reward_rate_per_block = 100; + let expiry_block = 25u64.into(); create_tokens(admin, vec![staking_asset_id.clone()]); assert_ok!(StakingRewards::create_pool( RuntimeOrigin::signed(admin), Box::new(staking_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, + expiry_block, None )); let pool_id = 0; From 13cccba9605a60a16f44a821199445b5329566b5 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 2 Apr 2024 18:51:56 +0400 Subject: [PATCH 015/159] test reward and expiry adjustment --- substrate/frame/asset-rewards/src/lib.rs | 58 ++-- substrate/frame/asset-rewards/src/tests.rs | 305 ++++++++++++--------- 2 files changed, 212 insertions(+), 151 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index afb91f421705..b031d9ea424b 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -80,7 +80,7 @@ pub type PoolId = u32; pub(crate) const PRECISION_SCALING_FACTOR: u32 = u32::MAX; /// A pool staker. -#[derive(Debug, Default, Decode, Encode, MaxEncodedLen, TypeInfo)] +#[derive(Debug, Default, Clone, Decode, Encode, MaxEncodedLen, TypeInfo)] pub struct PoolStakerInfo { /// Amount of tokens staked. amount: Balance, @@ -91,7 +91,7 @@ pub struct PoolStakerInfo { } /// A staking pool. -#[derive(Debug, Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] +#[derive(Debug, Clone, Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] pub struct PoolInfo { /// The asset that is staked in this pool. staking_asset_id: AssetId, @@ -120,7 +120,10 @@ pub mod pallet { traits::tokens::{AssetId, Preservation}, }; use frame_system::pallet_prelude::*; - use sp_runtime::traits::{AccountIdConversion, BadOrigin, EnsureDiv, Saturating}; + use sp_runtime::{ + traits::{AccountIdConversion, BadOrigin, EnsureDiv, Saturating}, + DispatchResult, + }; #[pallet::pallet] pub struct Pallet(_); @@ -463,11 +466,12 @@ pub mod pallet { new_reward_rate_per_block: T::Balance, ) -> DispatchResult { let caller = ensure_signed(origin)?; - let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; ensure!(pool_info.admin == caller, BadOrigin); Self::update_pool_rewards(&pool_id, None)?; + let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; pool_info.reward_rate_per_block = new_reward_rate_per_block; Pools::::insert(pool_id, pool_info); @@ -497,7 +501,7 @@ pub mod pallet { Ok(()) } - /// Modify a pool admin. + /// Modify a expiry block. /// /// TODO: Actually handle this in code pub fn set_pool_expiry_block( @@ -512,6 +516,8 @@ pub mod pallet { Error::::ExpiryBlockMustBeInTheFuture ); + Self::update_pool_rewards(&pool_id, None)?; + let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; ensure!(pool_info.admin == caller, BadOrigin); pool_info.expiry_block = new_expiry_block; @@ -557,25 +563,34 @@ pub mod pallet { } /// Update pool reward state, and optionally also a staker's rewards. + /// + /// Returns the updated pool info and optional staker info. pub fn update_pool_rewards( pool_id: &PoolId, staker: Option<&T::AccountId>, - ) -> DispatchResult { + ) -> Result< + ( + PoolInfo>, + Option>, + ), + DispatchError, + > { let reward_per_token = Self::reward_per_token(pool_id)?; let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; pool_info.last_update_block = frame_system::Pallet::::block_number(); pool_info.reward_per_token_stored = reward_per_token; - Pools::::insert(pool_id, pool_info); + Pools::::insert(pool_id, pool_info.clone()); if let Some(staker) = staker { let mut staker_info = PoolStakers::::get(pool_id, staker).unwrap_or_default(); staker_info.rewards = Self::derive_rewards(pool_id, staker)?; staker_info.reward_per_token_paid = reward_per_token; - PoolStakers::::insert(pool_id, staker, staker_info); + PoolStakers::::insert(pool_id, staker, staker_info.clone()); + return Ok((pool_info, Some(staker_info))); } - Ok(()) + Ok((pool_info, None)) } /// Derives the current reward per token for this pool. @@ -588,18 +603,19 @@ pub mod pallet { return Ok(pool_info.reward_per_token_stored) } - let blocks_elapsed: u32 = match frame_system::Pallet::::block_number() - .saturating_sub(pool_info.last_update_block) - .try_into() - { - Ok(b) => b, - Err(_) => return Err(Error::::BlockNumberConversionError.into()), - }; + let rewardable_blocks_elapsed: u32 = + match Self::last_block_reward_applicable(pool_info.expiry_block) + .saturating_sub(pool_info.last_update_block) + .try_into() + { + Ok(b) => b, + Err(_) => return Err(Error::::BlockNumberConversionError.into()), + }; Ok(pool_info.reward_per_token_stored.saturating_add( pool_info .reward_rate_per_block - .saturating_mul(blocks_elapsed.into()) + .saturating_mul(rewardable_blocks_elapsed.into()) .saturating_mul(PRECISION_SCALING_FACTOR.into()) .ensure_div(pool_info.total_tokens_staked)?, )) @@ -621,5 +637,13 @@ pub mod pallet { .ensure_div(PRECISION_SCALING_FACTOR.into())? .saturating_add(staker_info.rewards)) } + + fn last_block_reward_applicable(pool_expiry_block: BlockNumberFor) -> BlockNumberFor { + if frame_system::Pallet::::block_number() < pool_expiry_block { + frame_system::Pallet::::block_number() + } else { + pool_expiry_block + } + } } } diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 0e1f9e921c6d..8258a036ad92 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -573,139 +573,176 @@ mod set_pool_expiry_block { } } -mod integration { - use super::*; - - /// Assert that an amount has been hypothetically earned by a staker. - fn assert_hypothetically_earned( - staker: u128, - expected_earned: u128, - pool_id: u32, - reward_asset_id: NativeOrWithId, - ) { - hypothetically!({ - // Get the pre-harvest balance. - let balance_before: ::Balance = - <::Assets>::balance(reward_asset_id.clone(), &staker); - - // Harvest the rewards. - assert_ok!(StakingRewards::harvest_rewards( - RuntimeOrigin::signed(staker), - pool_id, - None - )); - - // Sanity check: staker rewards are reset to 0. - assert_eq!(PoolStakers::::get(pool_id, staker).unwrap().rewards, 0); - - // Check that the staker has earned the expected amount. - let balance_after = - <::Assets>::balance(reward_asset_id.clone(), &staker); - assert_eq!( - balance_after - balance_before, - ::Balance>>::into(expected_earned) - ); - }); - } - - #[test] - /// In this integration test scenario, we will consider 2 stakers each staking and unstaking at - /// different intervals, and assert their claimable rewards are as expected. - /// - /// Note: There are occasionally off by 1 errors due to rounding. In practice, this is - /// insignificant. - fn two_stakers() { - new_test_ext().execute_with(|| { - // Setup - let admin = 1; - let staker1 = 10u128; - let staker2 = 20; - let staking_asset_id = NativeOrWithId::::WithId(1); - let reward_asset_id = NativeOrWithId::::Native; - let reward_rate_per_block = 100; - let expiry_block = 25u64.into(); - create_tokens(admin, vec![staking_asset_id.clone()]); - assert_ok!(StakingRewards::create_pool( - RuntimeOrigin::signed(admin), - Box::new(staking_asset_id.clone()), - Box::new(reward_asset_id.clone()), - reward_rate_per_block, - expiry_block, - None - )); - let pool_id = 0; - let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); - <::Assets>::set_balance( - reward_asset_id.clone(), - &pool_account_id, - 100_000, - ); - <::Assets>::set_balance( - staking_asset_id.clone(), - &staker1, - 100_000, - ); - <::Assets>::set_balance( - staking_asset_id.clone(), - &staker2, - 100_000, - ); +/// Assert that an amount has been hypothetically earned by a staker. +fn assert_hypothetically_earned( + staker: u128, + expected_earned: u128, + pool_id: u32, + reward_asset_id: NativeOrWithId, +) { + hypothetically!({ + // Get the pre-harvest balance. + let balance_before: ::Balance = + <::Assets>::balance(reward_asset_id.clone(), &staker); + + // Harvest the rewards. + assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker), pool_id, None)); + + // Sanity check: staker rewards are reset to 0. + assert_eq!(PoolStakers::::get(pool_id, staker).unwrap().rewards, 0); + + // Check that the staker has earned the expected amount. + let balance_after = + <::Assets>::balance(reward_asset_id.clone(), &staker); + assert_eq!( + balance_after - balance_before, + ::Balance>>::into(expected_earned) + ); + }); +} - // Block 7: Staker 1 stakes 100 tokens. - System::set_block_number(7); - assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker1), pool_id, 100)); - // At this point - // - Staker 1 has earned 0 tokens. - // - Staker 1 is earning 100 tokens per block. - - // Check that Staker 1 has earned 0 tokens. - assert_hypothetically_earned(staker1, 0, pool_id, reward_asset_id.clone()); - - // Block 9: Staker 2 stakes 100 tokens. - System::set_block_number(9); - assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker2), pool_id, 100)); - // At this point - // - Staker 1 has earned 200 (100*2) tokens. - // - Staker 2 has earned 0 tokens. - // - Staker 1 is earning 50 tokens per block. - // - Staker 2 is earning 50 tokens per block. - - // Check that Staker 1 has earned 200 tokens and Staker 2 has earned 0 tokens. - assert_hypothetically_earned(staker1, 200, pool_id, reward_asset_id.clone()); - assert_hypothetically_earned(staker2, 0, pool_id, reward_asset_id.clone()); - - // Block 12: Staker 1 stakes an additional 100 tokens. - System::set_block_number(12); - assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker1), pool_id, 100)); - // At this point - // - Staker 1 has earned 350 (200 + (50 * 3)) tokens. - // - Staker 2 has earned 150 (50 * 3) tokens. - // - Staker 1 is earning 66.66 tokens per block. - // - Staker 2 is earning 33.33 tokens per block. - - // Check that Staker 1 has earned 350 tokens and Staker 2 has earned 150 tokens. - assert_hypothetically_earned(staker1, 349, pool_id, reward_asset_id.clone()); - assert_hypothetically_earned(staker2, 149, pool_id, reward_asset_id.clone()); - - // Block 22: Staker 1 unstakes 100 tokens. - System::set_block_number(22); - assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker1), pool_id, 100)); - // - Staker 1 has earned 1016 (350 + 66.66 * 10) tokens. - // - Staker 2 has earned 483 (150 + 33.33 * 10) tokens. - // - Staker 1 is earning 50 tokens per block. - // - Staker 2 is earning 50 tokens per block. - assert_hypothetically_earned(staker1, 1015, pool_id, reward_asset_id.clone()); - assert_hypothetically_earned(staker2, 483, pool_id, reward_asset_id.clone()); - - // Block 23: Staker 1 unstakes 100 tokens. - System::set_block_number(23); - assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker1), pool_id, 100)); - // - Staker 1 has earned 1065 (1015 + 50) tokens. - // - Staker 2 has earned 533 (483 + 50) tokens. - // - Staker 1 is earning 0 tokens per block. - // - Staker 2 is earning 100 tokens per block. - assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); - assert_hypothetically_earned(staker2, 533, pool_id, reward_asset_id.clone()); - }); - } +/// In this integration test scenario, we +/// 1. Consider 2 stakers each staking and unstaking at different intervals, and assert their +/// claimable rewards are as expected. +/// 2. Check that rewards are correctly halted after the pool's expiry block, and resume when the +/// pool is extended. +/// 3. Check that reward rates adjustment works correctly. +/// +/// Note: There are occasionally off by 1 errors due to rounding. In practice this is +/// insignificant. +#[test] +fn two_stakers_integration_test() { + new_test_ext().execute_with(|| { + // Setup + let admin = 1; + let staker1 = 10u128; + let staker2 = 20; + let staking_asset_id = NativeOrWithId::::WithId(1); + let reward_asset_id = NativeOrWithId::::Native; + let reward_rate_per_block = 100; + let expiry_block = 25u64.into(); + create_tokens(admin, vec![staking_asset_id.clone()]); + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::signed(admin), + Box::new(staking_asset_id.clone()), + Box::new(reward_asset_id.clone()), + reward_rate_per_block, + expiry_block, + None + )); + let pool_id = 0; + let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); + <::Assets>::set_balance( + reward_asset_id.clone(), + &pool_account_id, + 100_000, + ); + <::Assets>::set_balance(staking_asset_id.clone(), &staker1, 100_000); + <::Assets>::set_balance(staking_asset_id.clone(), &staker2, 100_000); + + // Block 7: Staker 1 stakes 100 tokens. + System::set_block_number(7); + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker1), pool_id, 100)); + // At this point + // - Staker 1 has earned 0 tokens. + // - Staker 1 is earning 100 tokens per block. + + // Check that Staker 1 has earned 0 tokens. + assert_hypothetically_earned(staker1, 0, pool_id, reward_asset_id.clone()); + + // Block 9: Staker 2 stakes 100 tokens. + System::set_block_number(9); + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker2), pool_id, 100)); + // At this point + // - Staker 1 has earned 200 (100*2) tokens. + // - Staker 2 has earned 0 tokens. + // - Staker 1 is earning 50 tokens per block. + // - Staker 2 is earning 50 tokens per block. + + // Check that Staker 1 has earned 200 tokens and Staker 2 has earned 0 tokens. + assert_hypothetically_earned(staker1, 200, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 0, pool_id, reward_asset_id.clone()); + + // Block 12: Staker 1 stakes an additional 100 tokens. + System::set_block_number(12); + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker1), pool_id, 100)); + // At this point + // - Staker 1 has earned 350 (200 + (50 * 3)) tokens. + // - Staker 2 has earned 150 (50 * 3) tokens. + // - Staker 1 is earning 66.66 tokens per block. + // - Staker 2 is earning 33.33 tokens per block. + + // Check that Staker 1 has earned 350 tokens and Staker 2 has earned 150 tokens. + assert_hypothetically_earned(staker1, 349, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 149, pool_id, reward_asset_id.clone()); + + // Block 22: Staker 1 unstakes 100 tokens. + System::set_block_number(22); + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker1), pool_id, 100)); + // - Staker 1 has earned 1016 (350 + 66.66 * 10) tokens. + // - Staker 2 has earned 483 (150 + 33.33 * 10) tokens. + // - Staker 1 is earning 50 tokens per block. + // - Staker 2 is earning 50 tokens per block. + assert_hypothetically_earned(staker1, 1015, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 483, pool_id, reward_asset_id.clone()); + + // Block 23: Staker 1 unstakes 100 tokens. + System::set_block_number(23); + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker1), pool_id, 100)); + // - Staker 1 has earned 1065 (1015 + 50) tokens. + // - Staker 2 has earned 533 (483 + 50) tokens. + // - Staker 1 is earning 0 tokens per block. + // - Staker 2 is earning 100 tokens per block. + assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 533, pool_id, reward_asset_id.clone()); + + // Block 50: Stakers should only have earned 2 blocks worth of tokens (expiry is 25). + System::set_block_number(50); + // - Staker 1 has earned 1065 tokens. + // - Staker 2 has earned 733 (533 + 2 * 100) tokens. + // - Staker 1 is earning 0 tokens per block. + // - Staker 2 is earning 0 tokens per block. + assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 733, pool_id, reward_asset_id.clone()); + + // Block 51: Extend the pool expiry block to 60. + System::set_block_number(51); + // - Staker 1 is earning 0 tokens per block. + // - Staker 2 is earning 100 tokens per block. + assert_ok!(StakingRewards::set_pool_expiry_block( + RuntimeOrigin::signed(admin), + pool_id, + 60u64 + )); + assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 733, pool_id, reward_asset_id.clone()); + + // Block 53: Check rewards are resumed. + // - Staker 1 has earned 1065 tokens. + // - Staker 2 has earned 933 (733 + 2 * 100) tokens. + // - Staker 2 is earning 100 tokens per block. + System::set_block_number(53); + assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 933, pool_id, reward_asset_id.clone()); + + // Block 55: Halve the block reward. + // - Staker 1 has earned 1065 tokens. + // - Staker 2 has earned 1133 (933 + 2 * 100) tokens. + // - Staker 2 is earning 50 tokens per block. + System::set_block_number(55); + assert_ok!(StakingRewards::set_pool_reward_rate_per_block( + RuntimeOrigin::signed(admin), + pool_id, + 50 + )); + assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 1133, pool_id, reward_asset_id.clone()); + + // Block 60: Check rewards were adjusted correctly. + // - Staker 1 has earned 1065 tokens. + // - Staker 2 has earned 1383 (1133 + 5 * 50) tokens. + System::set_block_number(60); + assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 1383, pool_id, reward_asset_id.clone()); + }); } From 5f397746a63114a15f39b4f81455f4f93aeefcf4 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 2 Apr 2024 19:01:15 +0400 Subject: [PATCH 016/159] check harvesting in integration test --- substrate/frame/asset-rewards/src/tests.rs | 60 +++++++++++++++++----- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 8258a036ad92..cf9fac9bd361 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -79,7 +79,6 @@ mod create_pool { #[test] fn success() { new_test_ext().execute_with(|| { - // Setup let user = 1; let staking_asset_id = NativeOrWithId::::Native; let reward_asset_id = NativeOrWithId::::WithId(1); @@ -88,9 +87,7 @@ mod create_pool { create_tokens(user, vec![reward_asset_id.clone()]); - // Create a pool with default admin. assert_eq!(NextPoolId::::get(), 0); - assert_ok!(StakingRewards::create_pool( RuntimeOrigin::signed(user), Box::new(staking_asset_id.clone()), @@ -396,7 +393,6 @@ mod unstake { #[test] fn fails_for_non_existent_pool() { new_test_ext().execute_with(|| { - // Setup let user = 1; let non_existent_pool_id = 999; @@ -601,19 +597,18 @@ fn assert_hypothetically_earned( }); } -/// In this integration test scenario, we -/// 1. Consider 2 stakers each staking and unstaking at different intervals, and assert their -/// claimable rewards are as expected. -/// 2. Check that rewards are correctly halted after the pool's expiry block, and resume when the +/// This integration test +/// 1. Considers 2 stakers each staking and unstaking at different intervals, asserts their +/// claimable rewards are adjusted as expected, and that harvesting works. +/// 2. Checks that rewards are correctly halted after the pool's expiry block, and resume when the /// pool is extended. -/// 3. Check that reward rates adjustment works correctly. +/// 3. Checks that reward rates adjustment works correctly. /// /// Note: There are occasionally off by 1 errors due to rounding. In practice this is /// insignificant. #[test] -fn two_stakers_integration_test() { +fn integration() { new_test_ext().execute_with(|| { - // Setup let admin = 1; let staker1 = 10u128; let staker2 = 20; @@ -738,11 +733,50 @@ fn two_stakers_integration_test() { assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); assert_hypothetically_earned(staker2, 1133, pool_id, reward_asset_id.clone()); + // Block 57: Staker 2 harvests their rewards. + System::set_block_number(57); + // - Staker 2 has earned 1233 (1133 + 2 * 50) tokens. + assert_hypothetically_earned(staker2, 1233, pool_id, reward_asset_id.clone()); + // Get the pre-harvest balance. + let balance_before: ::Balance = + <::Assets>::balance(reward_asset_id.clone(), &staker2); + assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker2), pool_id, None)); + let balance_after = + <::Assets>::balance(reward_asset_id.clone(), &staker2); + assert_eq!( + balance_after - balance_before, + ::Balance>>::into(1233) + ); + // Block 60: Check rewards were adjusted correctly. // - Staker 1 has earned 1065 tokens. - // - Staker 2 has earned 1383 (1133 + 5 * 50) tokens. + // - Staker 2 has earned 149 (3 * 50) tokens. System::set_block_number(60); assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); - assert_hypothetically_earned(staker2, 1383, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 149, pool_id, reward_asset_id.clone()); + + // Finally, check events. + assert_eq!( + events(), + [ + Event::PoolCreated { + creator: admin, + pool_id, + staking_asset_id, + reward_asset_id, + reward_rate_per_block: 100, + expiry_block: 25, + admin + }, + Event::Staked { who: staker1, pool_id, amount: 100 }, + Event::Staked { who: staker2, pool_id, amount: 100 }, + Event::Staked { who: staker1, pool_id, amount: 100 }, + Event::Unstaked { who: staker1, pool_id, amount: 100 }, + Event::Unstaked { who: staker1, pool_id, amount: 100 }, + Event::PoolExpiryBlockModified { pool_id, new_expiry_block: 60 }, + Event::PoolRewardRateModified { pool_id, new_reward_rate_per_block: 50 }, + Event::RewardsHarvested { who: staker2, staker: staker2, pool_id, amount: 1233 } + ] + ); }); } From cd65a3750eac28919ad41492e743d100e5dc4499 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 2 Apr 2024 19:03:58 +0400 Subject: [PATCH 017/159] remove redundant comment --- substrate/frame/asset-rewards/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index b031d9ea424b..ea4430f7b821 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -502,8 +502,6 @@ pub mod pallet { } /// Modify a expiry block. - /// - /// TODO: Actually handle this in code pub fn set_pool_expiry_block( origin: OriginFor, pool_id: PoolId, From 155fde788dd901313eb61d4dc7d1c62b12e3c457 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 3 Apr 2024 12:21:23 +0400 Subject: [PATCH 018/159] add assets to mock --- substrate/frame/asset-rewards/src/mock.rs | 33 +++++++++++++--------- substrate/frame/asset-rewards/src/tests.rs | 25 +++------------- 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index c179f0863dad..f3f87ce22fcb 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -142,19 +142,26 @@ impl Config for MockRuntime { pub(crate) fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - // pallet_assets::GenesisConfig:: { - // // Genesis assets: id, owner, is_sufficient, min_balance - // // pub assets: Vec<(T::AssetId, T::AccountId, bool, T::Balance)>, - // assets: vec![(1, 1, true, 10000)], - // // Genesis metadata: id, name, symbol, decimals - // // pub metadata: Vec<(T::AssetId, Vec, Vec, u8)>, - // metadata: vec![(1, b"test".to_vec(), b"TST".to_vec(), 18)], - // // Genesis accounts: id, account_id, balance - // // pub accounts: Vec<(T::AssetId, T::AccountId, T::Balance)>, - // accounts: vec![(1, 1, 10000)], - // } - // .assimilate_storage(&mut t) - // .unwrap(); + pallet_assets::GenesisConfig:: { + // Genesis assets: id, owner, is_sufficient, min_balance + // pub assets: Vec<(T::AssetId, T::AccountId, bool, T::Balance)>, + assets: vec![(1, 1, true, 10000)], + // Genesis metadata: id, name, symbol, decimals + // pub metadata: Vec<(T::AssetId, Vec, Vec, u8)>, + metadata: vec![(1, b"test".to_vec(), b"TST".to_vec(), 18)], + // Genesis accounts: id, account_id, balance + // pub accounts: Vec<(T::AssetId, T::AccountId, T::Balance)>, + accounts: vec![ + (1, 1, 10000), + (1, 2, 20000), + (1, 3, 30000), + (1, 4, 40000), + (1, 10, 40000), + (1, 20, 40000), + ], + } + .assimilate_storage(&mut t) + .unwrap(); pallet_balances::GenesisConfig:: { balances: vec![(1, 10000), (2, 20000), (3, 30000), (4, 40000), (10, 40000), (20, 40000)], diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index cf9fac9bd361..3a2e8682bff4 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -29,7 +29,6 @@ use sp_runtime::traits::BadOrigin; /// Useful for tests when you don't care about customising, or reusing the pool params. fn create_default_pool() { let staking_asset_id = NativeOrWithId::::WithId(1); - create_tokens(1, vec![staking_asset_id.clone()]); assert_ok!(StakingRewards::create_pool( RuntimeOrigin::signed(1), Box::new(staking_asset_id), @@ -40,17 +39,6 @@ fn create_default_pool() { )); } -fn create_tokens(owner: u128, tokens: Vec>) { - let ed = 1; - for token_id in tokens { - let asset_id = match token_id { - NativeOrWithId::WithId(id) => id, - _ => unreachable!("invalid token"), - }; - assert_ok!(Assets::force_create(RuntimeOrigin::root(), asset_id, owner, false, ed)); - } -} - fn events() -> Vec> { let result = System::events() .into_iter() @@ -85,8 +73,6 @@ mod create_pool { let reward_rate_per_block = 100; let expiry_block = 200u64; - create_tokens(user, vec![reward_asset_id.clone()]); - assert_eq!(NextPoolId::::get(), 0); assert_ok!(StakingRewards::create_pool( RuntimeOrigin::signed(user), @@ -243,7 +229,6 @@ mod create_pool { let reward_asset_id = NativeOrWithId::::WithId(1); let reward_rate_per_block = 100; let expiry_block = 100u64; - create_tokens(user, vec![reward_asset_id.clone()]); assert_err!( StakingRewards::create_pool( RuntimeOrigin::signed(user), @@ -266,7 +251,6 @@ mod create_pool { let reward_asset_id = NativeOrWithId::::WithId(1); let reward_rate_per_block = 100; let expiry_block = 100u64; - create_tokens(user, vec![reward_asset_id.clone()]); System::set_block_number(expiry_block + 1u64); assert_err!( StakingRewards::create_pool( @@ -326,6 +310,9 @@ mod stake { assert_eq!(Pools::::get(pool_id).unwrap().total_tokens_staked, 1500); // TODO: Check user's frozen balance is updated + + // Event is emitted. + assert_eq!(events(), []); }); } @@ -334,12 +321,9 @@ mod stake { new_test_ext().execute_with(|| { let user = 1; let staking_asset_id = NativeOrWithId::::WithId(1); - create_tokens(user, vec![staking_asset_id.clone()]); - - let non_existent_pool_id = 999; assert_err!( - StakingRewards::stake(RuntimeOrigin::signed(user), non_existent_pool_id, 1000), + StakingRewards::stake(RuntimeOrigin::signed(user), 999, 1000), Error::::NonExistentPool ); }); @@ -616,7 +600,6 @@ fn integration() { let reward_asset_id = NativeOrWithId::::Native; let reward_rate_per_block = 100; let expiry_block = 25u64.into(); - create_tokens(admin, vec![staking_asset_id.clone()]); assert_ok!(StakingRewards::create_pool( RuntimeOrigin::signed(admin), Box::new(staking_asset_id.clone()), From 5b47b1da9b2c19e912459cd37e68321efb18222f Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 3 Apr 2024 12:26:51 +0400 Subject: [PATCH 019/159] clean up test --- substrate/frame/asset-rewards/src/tests.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 3a2e8682bff4..3f877cadc66a 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -26,7 +26,8 @@ use sp_runtime::traits::BadOrigin; /// - Expiry block: 100 /// - Admin: 1 /// -/// Useful for tests when you don't care about customising, or reusing the pool params. +/// Useful to reduce boilerplate in tests when it's not important to customise or reusing pool +/// params. fn create_default_pool() { let staking_asset_id = NativeOrWithId::::WithId(1); assert_ok!(StakingRewards::create_pool( @@ -320,8 +321,6 @@ mod stake { fn fails_for_non_existent_pool() { new_test_ext().execute_with(|| { let user = 1; - let staking_asset_id = NativeOrWithId::::WithId(1); - assert_err!( StakingRewards::stake(RuntimeOrigin::signed(user), 999, 1000), Error::::NonExistentPool @@ -574,10 +573,7 @@ fn assert_hypothetically_earned( // Check that the staker has earned the expected amount. let balance_after = <::Assets>::balance(reward_asset_id.clone(), &staker); - assert_eq!( - balance_after - balance_before, - ::Balance>>::into(expected_earned) - ); + assert_eq!(balance_after - balance_before, expected_earned); }); } @@ -716,7 +712,7 @@ fn integration() { assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); assert_hypothetically_earned(staker2, 1133, pool_id, reward_asset_id.clone()); - // Block 57: Staker 2 harvests their rewards. + // Block 57: Staker2 harvests their rewards. System::set_block_number(57); // - Staker 2 has earned 1233 (1133 + 2 * 50) tokens. assert_hypothetically_earned(staker2, 1233, pool_id, reward_asset_id.clone()); @@ -726,10 +722,7 @@ fn integration() { assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker2), pool_id, None)); let balance_after = <::Assets>::balance(reward_asset_id.clone(), &staker2); - assert_eq!( - balance_after - balance_before, - ::Balance>>::into(1233) - ); + assert_eq!(balance_after - balance_before, 1233u128); // Block 60: Check rewards were adjusted correctly. // - Staker 1 has earned 1065 tokens. From 81aeb0c7b3961179e8d954b245bb1af9eefade8c Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 3 Apr 2024 13:34:29 +0400 Subject: [PATCH 020/159] pure internal functions --- substrate/frame/asset-rewards/src/lib.rs | 138 ++++++++++++++--------- 1 file changed, 83 insertions(+), 55 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index ea4430f7b821..d9c1688a53b9 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -43,6 +43,15 @@ //! //! ## Implementation Notes //! +//! Internal logic functions such as `update_pool_and_staker_rewards` where deliberately written +//! without any side-effects like storage interaction. +//! +//! Storage interaction such as reads and writes are instead all performed in the top level +//! pallet Call method, which while slightly more verbose, makes it much easier to understand the +//! code and reason about where side-effects occur in the pallet. +//! +//! ## Implementation Notes +//! //! The implementation is based on the [AccumulatedRewardsPerShare](https://dev.to/heymarkkop/understanding-sushiswaps-masterchef-staking-rewards-1m6f) algorithm. //! //! Rewards are calculated JIT (just-in-time), when a staker claims their rewards. @@ -79,6 +88,14 @@ pub type PoolId = u32; /// Multiplier to maintain precision when calculating rewards. pub(crate) const PRECISION_SCALING_FACTOR: u32 = u32::MAX; +/// Convenience type alias for `PoolInfo`. +pub type PoolInfoFor = PoolInfo< + ::AccountId, + ::AssetId, + ::Balance, + BlockNumberFor, +>; + /// A pool staker. #[derive(Debug, Default, Clone, Decode, Encode, MaxEncodedLen, TypeInfo)] pub struct PoolStakerInfo { @@ -320,7 +337,7 @@ pub mod pallet { }; // Create the pool. - let pool = PoolInfo::> { + let pool = PoolInfoFor:: { staking_asset_id: *staked_asset_id.clone(), reward_asset_id: *reward_asset_id.clone(), reward_rate_per_block, @@ -361,21 +378,22 @@ pub mod pallet { pub fn stake(origin: OriginFor, pool_id: PoolId, amount: T::Balance) -> DispatchResult { let caller = ensure_signed(origin)?; - // Always start by updating the pool rewards. - Self::update_pool_rewards(&pool_id, Some(&caller))?; + // Always start by updating staker and pool rewards. + let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + let staker_info = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); + let (mut pool_info, mut staker_info) = + Self::update_pool_and_staker_rewards(pool_info, staker_info)?; // Try to freeze the staker assets. // TODO: (blocked https://github.com/paritytech/polkadot-sdk/issues/3342) // Update Pools. - let mut pool = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - pool.total_tokens_staked.saturating_accrue(amount); - Pools::::insert(pool_id, pool); + pool_info.total_tokens_staked.saturating_accrue(amount); + Pools::::insert(pool_id, pool_info); // Update PoolStakers. - let mut staker = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); - staker.amount.saturating_accrue(amount); - PoolStakers::::insert(pool_id, &caller, staker); + staker_info.amount.saturating_accrue(amount); + PoolStakers::::insert(pool_id, &caller, staker_info); // Emit event. Self::deposit_event(Event::Staked { who: caller, pool_id, amount }); @@ -392,23 +410,24 @@ pub mod pallet { let caller = ensure_signed(origin)?; // Always start by updating the pool rewards. - Self::update_pool_rewards(&pool_id, Some(&caller))?; + let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + let staker_info = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); + let (mut pool_info, mut staker_info) = + Self::update_pool_and_staker_rewards(pool_info, staker_info)?; // Check the staker has enough staked tokens. - let mut staker = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); - ensure!(staker.amount >= amount, Error::::NotEnoughTokens); + ensure!(staker_info.amount >= amount, Error::::NotEnoughTokens); // Unfreeze staker assets. // TODO: (blocked https://github.com/paritytech/polkadot-sdk/issues/3342) // Update Pools. - let mut pool = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - pool.total_tokens_staked.saturating_reduce(amount); - Pools::::insert(pool_id, pool); + pool_info.total_tokens_staked.saturating_reduce(amount); + Pools::::insert(pool_id, pool_info); // Update PoolStakers. - staker.amount.saturating_reduce(amount); - PoolStakers::::insert(pool_id, &caller, staker); + staker_info.amount.saturating_reduce(amount); + PoolStakers::::insert(pool_id, &caller, staker_info); // Emit event. Self::deposit_event(Event::Unstaked { who: caller, pool_id, amount }); @@ -429,12 +448,13 @@ pub mod pallet { None => caller.clone(), }; - // Always start by updating the pool rewards. - Self::update_pool_rewards(&pool_id, Some(&staker))?; + // Always start by updating the pool and staker rewards. + let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + let staker_info = PoolStakers::::get(pool_id, &staker).unwrap_or_default(); + let (pool_info, mut staker_info) = + Self::update_pool_and_staker_rewards(pool_info, staker_info)?; // Transfer unclaimed rewards from the pool to the staker. - let mut staker_info = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); - let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; let pool_account_id = Self::pool_account_id(&pool_id)?; T::Assets::transfer( pool_info.reward_asset_id, @@ -469,9 +489,9 @@ pub mod pallet { let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; ensure!(pool_info.admin == caller, BadOrigin); - Self::update_pool_rewards(&pool_id, None)?; + // Always start by updating the pool rewards. + let mut pool_info = Self::update_pool_rewards(pool_info)?; - let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; pool_info.reward_rate_per_block = new_reward_rate_per_block; Pools::::insert(pool_id, pool_info); @@ -514,9 +534,10 @@ pub mod pallet { Error::::ExpiryBlockMustBeInTheFuture ); - Self::update_pool_rewards(&pool_id, None)?; + // Always start by updating the pool rewards. + let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + let mut pool_info = Self::update_pool_rewards(pool_info)?; - let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; ensure!(pool_info.admin == caller, BadOrigin); pool_info.expiry_block = new_expiry_block; Pools::::insert(pool_id, pool_info); @@ -560,43 +581,51 @@ pub mod pallet { } } - /// Update pool reward state, and optionally also a staker's rewards. + /// Computes update pool and staker reward state. + /// + /// Should be called prior to any operation involving a staker. + /// + /// Returns the updated pool and staker info. + /// + /// NOTE: this is a pure function without side effects. It does not modify any state + /// directly, that is the responsibility of the caller. + pub fn update_pool_and_staker_rewards( + mut pool_info: PoolInfoFor, + mut staker_info: PoolStakerInfo, + ) -> Result<(PoolInfoFor, PoolStakerInfo), DispatchError> { + let reward_per_token = Self::reward_per_token(&pool_info)?; + + pool_info.last_update_block = frame_system::Pallet::::block_number(); + pool_info.reward_per_token_stored = reward_per_token; + + staker_info.rewards = Self::derive_rewards(&pool_info, &staker_info)?; + staker_info.reward_per_token_paid = reward_per_token; + return Ok((pool_info, staker_info)); + } + + /// Computes update pool reward state. + /// + /// Should be called every time the pool is adjusted, and a staker is not involved. + /// + /// Returns the updated pool and staker info. /// - /// Returns the updated pool info and optional staker info. + /// NOTE: this is a pure function without side effects. It does not modify any state + /// directly, that is the responsibility of the caller. pub fn update_pool_rewards( - pool_id: &PoolId, - staker: Option<&T::AccountId>, - ) -> Result< - ( - PoolInfo>, - Option>, - ), - DispatchError, - > { - let reward_per_token = Self::reward_per_token(pool_id)?; + mut pool_info: PoolInfoFor, + ) -> Result, DispatchError> { + let reward_per_token = Self::reward_per_token(&pool_info)?; - let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; pool_info.last_update_block = frame_system::Pallet::::block_number(); pool_info.reward_per_token_stored = reward_per_token; - Pools::::insert(pool_id, pool_info.clone()); - - if let Some(staker) = staker { - let mut staker_info = PoolStakers::::get(pool_id, staker).unwrap_or_default(); - staker_info.rewards = Self::derive_rewards(pool_id, staker)?; - staker_info.reward_per_token_paid = reward_per_token; - PoolStakers::::insert(pool_id, staker, staker_info.clone()); - return Ok((pool_info, Some(staker_info))); - } - Ok((pool_info, None)) + Ok(pool_info) } /// Derives the current reward per token for this pool. /// /// Helper function for update_pool_rewards. Should not be called directly. - fn reward_per_token(pool_id: &PoolId) -> Result { - let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - + fn reward_per_token(pool_info: &PoolInfoFor) -> Result { if pool_info.total_tokens_staked.eq(&0u32.into()) { return Ok(pool_info.reward_per_token_stored) } @@ -623,11 +652,10 @@ pub mod pallet { /// /// Helper function for update_pool_rewards. Should not be called directly. fn derive_rewards( - pool_id: &PoolId, - staker: &T::AccountId, + pool_info: &PoolInfoFor, + staker_info: &PoolStakerInfo, ) -> Result { - let reward_per_token = Self::reward_per_token(pool_id)?; - let staker_info = PoolStakers::::get(pool_id, staker).unwrap_or_default(); + let reward_per_token = Self::reward_per_token(&pool_info)?; Ok(staker_info .amount From 90463a816bf693680cba79b1a1faaf8df95f013b Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 3 Apr 2024 13:47:28 +0400 Subject: [PATCH 021/159] harvest tests --- substrate/frame/asset-rewards/src/lib.rs | 5 +- substrate/frame/asset-rewards/src/tests.rs | 133 +++++++++++++++++++++ 2 files changed, 137 insertions(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index d9c1688a53b9..35e1eaa58f3a 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -280,6 +280,8 @@ pub mod pallet { NotEnoughTokens, /// An operation was attempted on a non-existent pool. NonExistentPool, + /// An operation was attempted on a non-existent pool. + NonExistentStaker, /// An operation was attempted using a non-existent asset. NonExistentAsset, /// There was an error converting a block number. @@ -450,7 +452,8 @@ pub mod pallet { // Always start by updating the pool and staker rewards. let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - let staker_info = PoolStakers::::get(pool_id, &staker).unwrap_or_default(); + let staker_info = + PoolStakers::::get(pool_id, &staker).ok_or(Error::::NonExistentStaker)?; let (pool_info, mut staker_info) = Self::update_pool_and_staker_rewards(pool_info, staker_info)?; diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 3f877cadc66a..2bd405c66918 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -406,6 +406,139 @@ mod unstake { } } +mod harvest_rewards { + use super::*; + + #[test] + fn success() { + new_test_ext().execute_with(|| { + let staker = 1; + let pool_id = 0; + let reward_asset_id = NativeOrWithId::::Native; + create_default_pool(); + let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); + <::Assets>::set_balance( + reward_asset_id.clone(), + &pool_account_id, + 100_000, + ); + + // Stake + System::set_block_number(10); + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker), pool_id, 1000)); + + // Harvest + System::set_block_number(20); + let balance_before: ::Balance = + <::Assets>::balance(reward_asset_id.clone(), &staker); + assert_ok!(StakingRewards::harvest_rewards( + RuntimeOrigin::signed(staker), + pool_id, + None + )); + let balance_after = + <::Assets>::balance(reward_asset_id.clone(), &staker); + + // Assert + assert_eq!( + balance_after - balance_before, + 10 * Pools::::get(pool_id).unwrap().reward_rate_per_block + ); + assert_eq!( + *events().last().unwrap(), + Event::::RewardsHarvested { + who: staker, + staker, + pool_id, + amount: 10 * Pools::::get(pool_id).unwrap().reward_rate_per_block + } + ); + }); + } + + #[test] + fn succeeds_when_harvesting_for_other_staker() { + new_test_ext().execute_with(|| { + let staker = 1; + let harvester = 2; + let pool_id = 0; + let reward_asset_id = NativeOrWithId::::Native; + create_default_pool(); + let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); + <::Assets>::set_balance( + reward_asset_id.clone(), + &pool_account_id, + 100_000, + ); + + // Stake + System::set_block_number(10); + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker), pool_id, 1000)); + System::set_block_number(20); + + // Harvest + let balance_before: ::Balance = + <::Assets>::balance(reward_asset_id.clone(), &staker); + assert_ok!(StakingRewards::harvest_rewards( + RuntimeOrigin::signed(harvester), + pool_id, + Some(staker) + )); + let balance_after = + <::Assets>::balance(reward_asset_id.clone(), &staker); + + // Assert + assert_eq!( + balance_after - balance_before, + 10 * Pools::::get(pool_id).unwrap().reward_rate_per_block + ); + assert_eq!( + *events().last().unwrap(), + Event::::RewardsHarvested { + who: harvester, + staker, + pool_id, + amount: 10 * Pools::::get(pool_id).unwrap().reward_rate_per_block + } + ); + }); + } + + #[test] + fn fails_for_non_existent_staker() { + new_test_ext().execute_with(|| { + let non_existent_staker = 999; + + create_default_pool(); + assert_err!( + StakingRewards::harvest_rewards( + RuntimeOrigin::signed(non_existent_staker), + 0, + None + ), + Error::::NonExistentStaker + ); + }); + } + + #[test] + fn fails_for_non_existent_pool() { + new_test_ext().execute_with(|| { + let staker = 1; + let non_existent_pool_id = 999; + + assert_err!( + StakingRewards::harvest_rewards( + RuntimeOrigin::signed(staker), + non_existent_pool_id, + None + ), + Error::::NonExistentPool + ); + }); + } +} + mod set_pool_admin { use super::*; From 36603691142b716efdfb2427acaf3c0506d42d02 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 3 Apr 2024 13:56:16 +0400 Subject: [PATCH 022/159] add dedicated set_pool_reward_rate_per_block tests --- substrate/frame/asset-rewards/src/tests.rs | 113 +++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 2bd405c66918..50cf5f35e9b6 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -685,6 +685,112 @@ mod set_pool_expiry_block { } } +mod set_pool_reward_rate_per_block { + use super::*; + + #[test] + fn state_is_modified_correctly() { + new_test_ext().execute_with(|| { + let admin = 1; + let pool_id = 0; + let new_reward_rate = 200; + create_default_pool(); + + assert_ok!(StakingRewards::set_pool_reward_rate_per_block( + RuntimeOrigin::signed(admin), + pool_id, + new_reward_rate + )); + + // Check state + assert_eq!( + Pools::::get(pool_id).unwrap().reward_rate_per_block, + new_reward_rate + ); + + // Check event + assert_eq!( + *events().last().unwrap(), + Event::::PoolRewardRateModified { + pool_id, + new_reward_rate_per_block: new_reward_rate + } + ); + }); + } + + #[test] + fn staker_rewards_are_affected_correctly() { + new_test_ext().execute_with(|| { + let admin = 1; + let staker = 2; + let pool_id = 0; + let new_reward_rate = 50; + create_default_pool(); + + // Stake some tokens, and accumulate 10 blocks of rewards at the default pool rate (100) + System::set_block_number(10); + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker), pool_id, 1000)); + System::set_block_number(20); + + // Halve the reward rate + assert_ok!(StakingRewards::set_pool_reward_rate_per_block( + RuntimeOrigin::signed(admin), + pool_id, + new_reward_rate + )); + + // Accumulate 10 blocks of rewards at the new rate + System::set_block_number(30); + + // Check that rewards are calculated correctly with the updated rate + assert_hypothetically_earned( + staker, + 10 * 100 + 10 * new_reward_rate - 1, // -1 due to rounding + pool_id, + NativeOrWithId::::Native, + ); + }); + } + + #[test] + fn fails_for_non_existent_pool() { + new_test_ext().execute_with(|| { + let admin = 1; + let non_existent_pool_id = 999; + let new_reward_rate = 200; + + assert_err!( + StakingRewards::set_pool_reward_rate_per_block( + RuntimeOrigin::signed(admin), + non_existent_pool_id, + new_reward_rate + ), + Error::::NonExistentPool + ); + }); + } + + #[test] + fn fails_for_non_admin() { + new_test_ext().execute_with(|| { + let non_admin = 2; + let pool_id = 0; + let new_reward_rate = 200; + create_default_pool(); + + assert_err!( + StakingRewards::set_pool_reward_rate_per_block( + RuntimeOrigin::signed(non_admin), + pool_id, + new_reward_rate + ), + BadOrigin + ); + }); + } +} + /// Assert that an amount has been hypothetically earned by a staker. fn assert_hypothetically_earned( staker: u128, @@ -693,6 +799,13 @@ fn assert_hypothetically_earned( reward_asset_id: NativeOrWithId, ) { hypothetically!({ + let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); + <::Assets>::set_balance( + reward_asset_id.clone(), + &pool_account_id, + 100_000, + ); + // Get the pre-harvest balance. let balance_before: ::Balance = <::Assets>::balance(reward_asset_id.clone(), &staker); From 16bc43bf5536b64439b143ef8cf1374c0938fc11 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 3 Apr 2024 14:49:38 +0400 Subject: [PATCH 023/159] set up pool 0 account with rewards --- substrate/frame/asset-rewards/src/mock.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index f3f87ce22fcb..66e553b77ee0 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -163,8 +163,17 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities { .assimilate_storage(&mut t) .unwrap(); + let pool_zero_account_id = 31086825966906540362769395565; pallet_balances::GenesisConfig:: { - balances: vec![(1, 10000), (2, 20000), (3, 30000), (4, 40000), (10, 40000), (20, 40000)], + balances: vec![ + (1, 10000), + (2, 20000), + (3, 30000), + (4, 40000), + (10, 40000), + (20, 40000), + (pool_zero_account_id, 100_000), // Top up the default pool account id + ], } .assimilate_storage(&mut t) .unwrap(); From d5c465923f7acf880fac1370a301c081dfb422bb Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 3 Apr 2024 14:50:35 +0400 Subject: [PATCH 024/159] improve expiry block tests --- substrate/frame/asset-rewards/src/tests.rs | 103 ++++++++++++++------- 1 file changed, 69 insertions(+), 34 deletions(-) diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 50cf5f35e9b6..258c0ebdb1d8 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -416,12 +416,6 @@ mod harvest_rewards { let pool_id = 0; let reward_asset_id = NativeOrWithId::::Native; create_default_pool(); - let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); - <::Assets>::set_balance( - reward_asset_id.clone(), - &pool_account_id, - 100_000, - ); // Stake System::set_block_number(10); @@ -464,12 +458,6 @@ mod harvest_rewards { let pool_id = 0; let reward_asset_id = NativeOrWithId::::Native; create_default_pool(); - let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); - <::Assets>::set_balance( - reward_asset_id.clone(), - &pool_account_id, - 100_000, - ); // Stake System::set_block_number(10); @@ -608,14 +596,13 @@ mod set_pool_expiry_block { use super::*; #[test] - fn success() { + fn updates_state_correctly() { new_test_ext().execute_with(|| { let admin = 1; let pool_id = 0; let new_expiry_block = 200u64; create_default_pool(); - // Modify the pool expiry block assert_ok!(StakingRewards::set_pool_expiry_block( RuntimeOrigin::signed(admin), pool_id, @@ -623,11 +610,76 @@ mod set_pool_expiry_block { )); // Check state + assert_eq!(Pools::::get(pool_id).unwrap().expiry_block, new_expiry_block); assert_eq!( *events().last().unwrap(), Event::::PoolExpiryBlockModified { pool_id, new_expiry_block } ); - assert_eq!(Pools::::get(pool_id).unwrap().expiry_block, new_expiry_block); + }); + } + + #[test] + fn extends_reward_accumulation() { + new_test_ext().execute_with(|| { + let admin = 1; + let staker = 2; + let pool_id = 0; + let new_expiry_block = 200u64; + create_default_pool(); + + // Regular reward accumulation + System::set_block_number(10); + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker), pool_id, 1000)); + System::set_block_number(20); + assert_hypothetically_earned(staker, 100 * 10, pool_id, NativeOrWithId::::Native); + + // Expiry was block 100, or only earned 90 blocks at block 150 + System::set_block_number(150); + assert_hypothetically_earned(staker, 100 * 90, pool_id, NativeOrWithId::::Native); + + // Extend expiry 50 more blocks + assert_ok!(StakingRewards::set_pool_expiry_block( + RuntimeOrigin::signed(admin), + pool_id, + new_expiry_block + )); + System::set_block_number(300); + + // Staker has been in pool with rewards active for 140 blocks total + assert_hypothetically_earned(staker, 100 * 140, pool_id, NativeOrWithId::::Native); + }); + } + + #[test] + fn halts_reward_accumulation() { + new_test_ext().execute_with(|| { + let admin = 1; + let staker = 2; + let pool_id = 0; + create_default_pool(); + + // Earn 10 blocks of rewards + System::set_block_number(10); + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker), pool_id, 1000)); + System::set_block_number(20); + assert_hypothetically_earned(staker, 100 * 10, pool_id, NativeOrWithId::::Native); + + // Cut off rewards earlier than original expiry + System::set_block_number(21); + assert_ok!(StakingRewards::set_pool_expiry_block( + RuntimeOrigin::signed(admin), + pool_id, + 30 + )); + System::set_block_number(50); + + // Staker has been in pool with rewards active for 20 blocks total + assert_hypothetically_earned( + staker, + 100 * 20 - 1, // -1 rounding error + pool_id, + NativeOrWithId::::Native, + ); }); } @@ -674,11 +726,9 @@ mod set_pool_expiry_block { let admin = 1; let pool_id = 0; create_default_pool(); - - System::set_block_number(5000); - + System::set_block_number(50); assert_err!( - StakingRewards::set_pool_expiry_block(RuntimeOrigin::signed(admin), pool_id, 2u64), + StakingRewards::set_pool_expiry_block(RuntimeOrigin::signed(admin), pool_id, 40u64), Error::::ExpiryBlockMustBeInTheFuture ); }); @@ -799,13 +849,6 @@ fn assert_hypothetically_earned( reward_asset_id: NativeOrWithId, ) { hypothetically!({ - let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); - <::Assets>::set_balance( - reward_asset_id.clone(), - &pool_account_id, - 100_000, - ); - // Get the pre-harvest balance. let balance_before: ::Balance = <::Assets>::balance(reward_asset_id.clone(), &staker); @@ -851,14 +894,6 @@ fn integration() { None )); let pool_id = 0; - let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); - <::Assets>::set_balance( - reward_asset_id.clone(), - &pool_account_id, - 100_000, - ); - <::Assets>::set_balance(staking_asset_id.clone(), &staker1, 100_000); - <::Assets>::set_balance(staking_asset_id.clone(), &staker2, 100_000); // Block 7: Staker 1 stakes 100 tokens. System::set_block_number(7); From 3b47813d9343f1bddae6c892b7f0a8fad2a13b5d Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 3 Apr 2024 14:55:35 +0400 Subject: [PATCH 025/159] rearrange test --- substrate/frame/asset-rewards/src/tests.rs | 49 +++++++++++----------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 258c0ebdb1d8..720082190f2d 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -40,6 +40,30 @@ fn create_default_pool() { )); } +fn assert_hypothetically_earned( + staker: u128, + expected_earned: u128, + pool_id: u32, + reward_asset_id: NativeOrWithId, +) { + hypothetically!({ + // Get the pre-harvest balance. + let balance_before: ::Balance = + <::Assets>::balance(reward_asset_id.clone(), &staker); + + // Harvest the rewards. + assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker), pool_id, None)); + + // Sanity check: staker rewards are reset to 0. + assert_eq!(PoolStakers::::get(pool_id, staker).unwrap().rewards, 0); + + // Check that the staker has earned the expected amount. + let balance_after = + <::Assets>::balance(reward_asset_id.clone(), &staker); + assert_eq!(balance_after - balance_before, expected_earned); + }); +} + fn events() -> Vec> { let result = System::events() .into_iter() @@ -841,31 +865,6 @@ mod set_pool_reward_rate_per_block { } } -/// Assert that an amount has been hypothetically earned by a staker. -fn assert_hypothetically_earned( - staker: u128, - expected_earned: u128, - pool_id: u32, - reward_asset_id: NativeOrWithId, -) { - hypothetically!({ - // Get the pre-harvest balance. - let balance_before: ::Balance = - <::Assets>::balance(reward_asset_id.clone(), &staker); - - // Harvest the rewards. - assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker), pool_id, None)); - - // Sanity check: staker rewards are reset to 0. - assert_eq!(PoolStakers::::get(pool_id, staker).unwrap().rewards, 0); - - // Check that the staker has earned the expected amount. - let balance_after = - <::Assets>::balance(reward_asset_id.clone(), &staker); - assert_eq!(balance_after - balance_before, expected_earned); - }); -} - /// This integration test /// 1. Considers 2 stakers each staking and unstaking at different intervals, asserts their /// claimable rewards are adjusted as expected, and that harvesting works. From aef1b4b8bbbe9e0bea6094e35a5d23ba3514bd91 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 3 Apr 2024 15:07:56 +0400 Subject: [PATCH 026/159] add deposit extrinsic tests --- substrate/frame/asset-rewards/src/tests.rs | 58 +++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 720082190f2d..8de62643b59c 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -17,7 +17,7 @@ use crate::{mock::*, *}; use frame_support::{assert_err, assert_ok, hypothetically, traits::fungible::NativeOrWithId}; -use sp_runtime::traits::BadOrigin; +use sp_runtime::{traits::BadOrigin, ArithmeticError}; /// Creates a basic pool with values: /// - Staking asset: 1 @@ -865,6 +865,62 @@ mod set_pool_reward_rate_per_block { } } +mod deposit_reward_tokens { + use super::*; + + #[test] + fn success() { + new_test_ext().execute_with(|| { + let depositor = 1; + let pool_id = 0; + let amount = 1000; + let reward_asset_id = NativeOrWithId::::Native; + create_default_pool(); + let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); + + let depositor_balance_before = + <::Assets>::balance(reward_asset_id.clone(), &depositor); + let pool_balance_before = <::Assets>::balance( + reward_asset_id.clone(), + &pool_account_id, + ); + assert_ok!(StakingRewards::deposit_reward_tokens( + RuntimeOrigin::signed(depositor), + pool_id, + amount + )); + let depositor_balance_after = + <::Assets>::balance(reward_asset_id.clone(), &depositor); + let pool_balance_after = + <::Assets>::balance(reward_asset_id, &pool_account_id); + + assert_eq!(pool_balance_after - pool_balance_before, amount); + assert_eq!(depositor_balance_before - depositor_balance_after, amount); + }); + } + + #[test] + fn fails_for_non_existent_pool() { + new_test_ext().execute_with(|| { + assert_err!( + StakingRewards::deposit_reward_tokens(RuntimeOrigin::signed(1), 999, 100), + Error::::NonExistentPool + ); + }); + } + + #[test] + fn fails_for_insufficient_balance() { + new_test_ext().execute_with(|| { + create_default_pool(); + assert_err!( + StakingRewards::deposit_reward_tokens(RuntimeOrigin::signed(1), 0, 100_000_000), + ArithmeticError::Underflow + ); + }); + } +} + /// This integration test /// 1. Considers 2 stakers each staking and unstaking at different intervals, asserts their /// claimable rewards are adjusted as expected, and that harvesting works. From a4c6067bc24bcdc8de1bd43e3c8d1c6c9411ac9e Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 3 Apr 2024 15:11:37 +0400 Subject: [PATCH 027/159] clean up mock --- substrate/frame/asset-rewards/src/mock.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index 66e553b77ee0..c0f23bb33bff 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -105,14 +105,12 @@ ord_parameter_types! { pub const AssetConversionOrigin: u128 = AccountIdConversion::::into_account_truncating(&StakingRewardsPalletId::get()); } +// Set account id 1 to the permissioned creator pub struct MockPermissionedPoolCreator; impl EnsureOrigin for MockPermissionedPoolCreator { type Success = (); - fn try_origin( - origin: RuntimeOrigin, - // key: &RuntimeParametersKey, - ) -> Result { + fn try_origin(origin: RuntimeOrigin) -> Result { // Set account 1 to admin in tests if ensure_signed(origin.clone()).map_or(false, |acc| acc == 1) { return Ok(()); @@ -122,7 +120,7 @@ impl EnsureOrigin for MockPermissionedPoolCreator { } #[cfg(feature = "runtime-benchmarks")] - fn try_successful_origin() -> Result { + fn try_successful_origin() -> Result { todo!() } } @@ -135,7 +133,6 @@ impl Config for MockRuntime { type Balance = ::Balance; type Assets = NativeAndAssets; type PalletId = StakingRewardsPalletId; - // allow account id 1 to be permissioned creator type PermissionedPoolCreator = MockPermissionedPoolCreator; } From cfb3dfaae215d7f279aa49a34298fcac6fea3bf4 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 3 Apr 2024 15:59:19 +0400 Subject: [PATCH 028/159] update docs --- substrate/frame/asset-rewards/src/lib.rs | 54 +++++++-- substrate/frame/asset-rewards/src/tests.rs | 121 +++++++++++++++++++++ 2 files changed, 165 insertions(+), 10 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 35e1eaa58f3a..50ce231bc412 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -23,18 +23,23 @@ //! //! Governance can create a new incentive program for a fungible asset by creating a new pool. //! -//! When creating the pool, governance specifies a 'staking asset', 'reward asset', and 'reward rate -//! per block'. +//! When creating the pool, governance specifies a 'staking asset', 'reward asset', 'reward rate +//! per block', and an 'expiry block'. //! -//! Once the pool is created, holders of the 'staking asset' can stake them in this pallet (creating -//! a new Freeze). Once staked, the staker begins accumulating the right to claim the 'reward asset' -//! each block, proportional to their share of the total staked tokens in the pool. +//! Once the pool is created, holders of the 'staking asset' can stake them in this pallet, which +//! puts a Freeze on the asset. +//! +//! Once staked, the staker begins accumulating the right to claim the 'reward asset' each block, +//! proportional to their share of the total staked tokens in the pool. //! //! Reward assets pending distribution are held in an account derived from the pallet ID and a //! unique pool ID. //! //! Care should be taken to keep pool accounts adequately funded with the reward asset. //! +//! The pool administator can adjust the reward rate per block, the expiry block, and the admin +//! after the pool is created. +//! //! ## Permissioning //! //! Currently, pool creation and management is permissioned and restricted to a configured Origin. @@ -50,14 +55,23 @@ //! pallet Call method, which while slightly more verbose, makes it much easier to understand the //! code and reason about where side-effects occur in the pallet. //! -//! ## Implementation Notes +//! ## Rewards Algorithm //! -//! The implementation is based on the [AccumulatedRewardsPerShare](https://dev.to/heymarkkop/understanding-sushiswaps-masterchef-staking-rewards-1m6f) algorithm. +//! The rewards algorithm is based on the Synthetix [StakingRewards.sol](https://github.com/Synthetixio/synthetix/blob/develop/contracts/StakingRewards.sol) +//! smart contract. //! -//! Rewards are calculated JIT (just-in-time), when a staker claims their rewards. +//! Rewards are calculated JIT (just-in-time), and all operations are O(1) making the approach +//! scalable to many pools and stakers. //! -//! All operations are O(1), allowing the approach to scale to an arbitrary amount of pools and -//! stakers. +//! The approach is widly used across the Ethereum ecosystem, there is also quite battle tested. +//! +//! ### Resources +//! +//! - [This YouTube video series](https://www.youtube.com/watch?v=6ZO5aYg1GI8), which walks through +//! the math of the algorithm. +//! - [This dev.to article](https://dev.to/heymarkkop/understanding-sushiswaps-masterchef-staking-rewards-1m6f), +//! which explains the algorithm of the SushiSwap MasterChef staking. While not identical to the +//! Synthetix approach, they are very similar. #![deny(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] @@ -572,6 +586,26 @@ pub mod pallet { )?; Ok(()) } + + /// Permissioned method to withdraw reward tokens from a pool. + pub fn withdraw_reward_tokens( + origin: OriginFor, + pool_id: PoolId, + amount: T::Balance, + ) -> DispatchResult { + let caller = ensure_signed(origin)?; + let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + ensure!(pool_info.admin == caller, BadOrigin); + T::Assets::transfer( + pool_info.reward_asset_id, + &caller, + &Self::pool_account_id(&pool_id)?, + amount, + Preservation::Preserve, + )?; + + Ok(()) + } } impl Pallet { diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 8de62643b59c..798840962022 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -921,6 +921,127 @@ mod deposit_reward_tokens { } } +mod withdraw_reward_tokens { + use super::*; + + #[test] + fn success() { + new_test_ext().execute_with(|| { + let admin = 1; + let pool_id = 0; + let reward_asset_id = NativeOrWithId::::Native; + let initial_deposit = 10; + let withdraw_amount = 5; + create_default_pool(); + let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); + + let admin_balance_before = + <::Assets>::balance(reward_asset_id.clone(), &admin); + let pool_balance_before = <::Assets>::balance( + reward_asset_id.clone(), + &pool_account_id, + ); + + // Deposit initial reward tokens + assert_ok!(StakingRewards::deposit_reward_tokens( + RuntimeOrigin::signed(admin), + pool_id, + initial_deposit + )); + + // Withdraw some tokens + assert_ok!(StakingRewards::withdraw_reward_tokens( + RuntimeOrigin::signed(admin), + pool_id, + withdraw_amount + )); + + let admin_balance_after = + <::Assets>::balance(reward_asset_id.clone(), &admin); + let pool_balance_after = + <::Assets>::balance(reward_asset_id, &pool_account_id); + + assert_eq!( + <::Assets>::balance( + reward_asset_id.clone(), + &pool_account_id + ), + initial_deposit - withdraw_amount + ); + assert_eq!( + <::Assets>::balance(reward_asset_id, &admin), + withdraw_amount + ); + }); + } + + // #[test] + // fn fails_for_non_existent_pool() { + // new_test_ext().execute_with(|| { + // let admin = 1; + // let non_existent_pool_id = 999; + // let withdraw_amount = 5000; + // + // assert_err!( + // StakingRewards::withdraw_reward_tokens( + // RuntimeOrigin::signed(admin), + // non_existent_pool_id, + // withdraw_amount + // ), + // Error::::NonExistentPool + // ); + // }); + // } + // + // #[test] + // fn fails_for_non_admin() { + // new_test_ext().execute_with(|| { + // let non_admin = 2; + // let pool_id = 0; + // let withdraw_amount = 5000; + // create_default_pool(); + // + // assert_err!( + // StakingRewards::withdraw_reward_tokens( + // RuntimeOrigin::signed(non_admin), + // pool_id, + // withdraw_amount + // ), + // BadOrigin + // ); + // }); + // } + // + // #[test] + // fn fails_for_insufficient_pool_balance() { + // new_test_ext().execute_with(|| { + // let admin = 1; + // let pool_id = 0; + // let reward_asset_id = NativeOrWithId::::Native; + // let initial_deposit = 10000; + // let withdraw_amount = 15000; + // create_default_pool(); + // + // // Deposit initial reward tokens + // let pool_account = StakingRewards::pool_account_id(&pool_id).unwrap(); + // <::Assets>::set_balance( + // reward_asset_id, + // &pool_account, + // initial_deposit, + // ); + // + // assert_err!( + // StakingRewards::withdraw_reward_tokens( + // RuntimeOrigin::signed(admin), + // pool_id, + // withdraw_amount + // ), + // assets::Error::::BalanceLow + // ); + // }); + // } +} + /// This integration test /// 1. Considers 2 stakers each staking and unstaking at different intervals, asserts their /// claimable rewards are adjusted as expected, and that harvesting works. From 9f2c4fa4c71c817b2c4c678bdd73995ce8ff5f94 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 3 Apr 2024 16:09:30 +0400 Subject: [PATCH 029/159] test withdraw reward token method --- substrate/frame/asset-rewards/src/lib.rs | 2 +- substrate/frame/asset-rewards/src/tests.rs | 145 +++++++++------------ 2 files changed, 61 insertions(+), 86 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 50ce231bc412..8bb927823df0 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -598,8 +598,8 @@ pub mod pallet { ensure!(pool_info.admin == caller, BadOrigin); T::Assets::transfer( pool_info.reward_asset_id, - &caller, &Self::pool_account_id(&pool_id)?, + &caller, amount, Preservation::Preserve, )?; diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 798840962022..90d8e11b89b1 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -17,7 +17,7 @@ use crate::{mock::*, *}; use frame_support::{assert_err, assert_ok, hypothetically, traits::fungible::NativeOrWithId}; -use sp_runtime::{traits::BadOrigin, ArithmeticError}; +use sp_runtime::{traits::BadOrigin, ArithmeticError, TokenError}; /// Creates a basic pool with values: /// - Staking asset: 1 @@ -935,13 +935,6 @@ mod withdraw_reward_tokens { create_default_pool(); let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); - let admin_balance_before = - <::Assets>::balance(reward_asset_id.clone(), &admin); - let pool_balance_before = <::Assets>::balance( - reward_asset_id.clone(), - &pool_account_id, - ); - // Deposit initial reward tokens assert_ok!(StakingRewards::deposit_reward_tokens( RuntimeOrigin::signed(admin), @@ -950,96 +943,78 @@ mod withdraw_reward_tokens { )); // Withdraw some tokens + let admin_balance_before = + <::Assets>::balance(reward_asset_id.clone(), &admin); + let pool_balance_before = <::Assets>::balance( + reward_asset_id.clone(), + &pool_account_id, + ); assert_ok!(StakingRewards::withdraw_reward_tokens( RuntimeOrigin::signed(admin), pool_id, withdraw_amount )); - let admin_balance_after = <::Assets>::balance(reward_asset_id.clone(), &admin); - let pool_balance_after = - <::Assets>::balance(reward_asset_id, &pool_account_id); + let pool_balance_after = <::Assets>::balance( + reward_asset_id.clone(), + &pool_account_id, + ); - assert_eq!( - <::Assets>::balance( - reward_asset_id.clone(), - &pool_account_id - ), - initial_deposit - withdraw_amount + assert_eq!(pool_balance_after, pool_balance_before - withdraw_amount); + assert_eq!(admin_balance_after, admin_balance_before + withdraw_amount); + }); + } + + #[test] + fn fails_for_non_existent_pool() { + new_test_ext().execute_with(|| { + assert_err!( + StakingRewards::withdraw_reward_tokens(RuntimeOrigin::signed(1), 900, 100), + Error::::NonExistentPool ); - assert_eq!( - <::Assets>::balance(reward_asset_id, &admin), - withdraw_amount + }); + } + + #[test] + fn fails_for_non_admin() { + new_test_ext().execute_with(|| { + create_default_pool(); + assert_err!( + StakingRewards::withdraw_reward_tokens(RuntimeOrigin::signed(5), 0, 100), + BadOrigin ); }); } - // #[test] - // fn fails_for_non_existent_pool() { - // new_test_ext().execute_with(|| { - // let admin = 1; - // let non_existent_pool_id = 999; - // let withdraw_amount = 5000; - // - // assert_err!( - // StakingRewards::withdraw_reward_tokens( - // RuntimeOrigin::signed(admin), - // non_existent_pool_id, - // withdraw_amount - // ), - // Error::::NonExistentPool - // ); - // }); - // } - // - // #[test] - // fn fails_for_non_admin() { - // new_test_ext().execute_with(|| { - // let non_admin = 2; - // let pool_id = 0; - // let withdraw_amount = 5000; - // create_default_pool(); - // - // assert_err!( - // StakingRewards::withdraw_reward_tokens( - // RuntimeOrigin::signed(non_admin), - // pool_id, - // withdraw_amount - // ), - // BadOrigin - // ); - // }); - // } - // - // #[test] - // fn fails_for_insufficient_pool_balance() { - // new_test_ext().execute_with(|| { - // let admin = 1; - // let pool_id = 0; - // let reward_asset_id = NativeOrWithId::::Native; - // let initial_deposit = 10000; - // let withdraw_amount = 15000; - // create_default_pool(); - // - // // Deposit initial reward tokens - // let pool_account = StakingRewards::pool_account_id(&pool_id).unwrap(); - // <::Assets>::set_balance( - // reward_asset_id, - // &pool_account, - // initial_deposit, - // ); - // - // assert_err!( - // StakingRewards::withdraw_reward_tokens( - // RuntimeOrigin::signed(admin), - // pool_id, - // withdraw_amount - // ), - // assets::Error::::BalanceLow - // ); - // }); - // } + #[test] + fn fails_for_insufficient_pool_balance() { + new_test_ext().execute_with(|| { + let admin = 1; + let pool_id = 0; + let reward_asset_id = NativeOrWithId::::Native; + let initial_deposit = 10000; + let withdraw_amount = 15000; + create_default_pool(); + + // Deposit initial reward tokens + let pool_account = StakingRewards::pool_account_id(&pool_id).unwrap(); + <::Assets>::set_balance( + reward_asset_id, + &pool_account, + initial_deposit, + ); + + assert_err!( + StakingRewards::withdraw_reward_tokens( + RuntimeOrigin::signed(admin), + pool_id, + withdraw_amount + ), + TokenError::FundsUnavailable + ); + }); + } } /// This integration test From 7078d0343cd4f2066fd63c1b851e572c61cfa734 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 5 Apr 2024 11:56:23 +0400 Subject: [PATCH 030/159] update comment --- substrate/frame/asset-rewards/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 8bb927823df0..81df78cbfed4 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -385,7 +385,8 @@ pub mod pallet { /// Removes an existing reward pool. /// - /// TODO decide how to manage clean up of stakers from a removed pool. + /// TODO decide if we want to implement this functionality, and if so, how to manage clean + /// up of stakers from a removed pool. pub fn remove_pool(_origin: OriginFor, _pool_id: PoolId) -> DispatchResult { todo!() } From 740a7493dd16f8e07a41c0ba6a960efe8657f059 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 5 Apr 2024 15:28:28 +0400 Subject: [PATCH 031/159] wip benchmarks --- .../frame/asset-rewards/src/benchmarking.rs | 116 ++++++++++++++++++ substrate/frame/asset-rewards/src/lib.rs | 18 ++- substrate/frame/asset-rewards/src/mock.rs | 2 + substrate/frame/asset-rewards/src/tests.rs | 36 +++--- 4 files changed, 149 insertions(+), 23 deletions(-) create mode 100644 substrate/frame/asset-rewards/src/benchmarking.rs diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs new file mode 100644 index 000000000000..d351bb059444 --- /dev/null +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -0,0 +1,116 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Asset Rewards pallet benchmarking. + +use super::*; +use crate::Pallet as AssetRewards; +use frame_benchmarking::{v2::*, whitelisted_caller}; +use frame_support::{ + assert_ok, + traits::fungibles::{Create, Inspect, Mutate}, +}; +use frame_system::RawOrigin as SystemOrigin; +use sp_runtime::traits::One; +use sp_std::prelude::*; + +/// Benchmark Helper +pub trait BenchmarkHelper { + /// Returns a valid assets pair for the pool creation. + /// + /// When a specific asset, such as the native asset, is required in every pool, it should be + /// returned for each odd-numbered seed. + fn to_asset_id(seed: u32) -> AssetId; + fn to_account_id(seed: u32) -> AccountId; +} + +impl BenchmarkHelper for () +where + AssetId: From, + AccountId: From, +{ + fn to_asset_id(seed: u32) -> AssetId { + seed.into() + } + fn to_account_id(seed: u32) -> AccountId { + seed.into() + } +} + +/// Create the `asset` and mint the `amount` for the `caller`. +fn create_asset(caller: &T::AccountId, asset: &T::AssetId, amount: T::Balance) +where + T::Assets: Create + Mutate, +{ + if !T::Assets::asset_exists(asset.clone()) { + assert_ok!(T::Assets::create(asset.clone(), caller.clone(), true, T::Balance::one())); + } + assert_ok!(T::Assets::mint_into( + asset.clone(), + &caller, + amount + T::Assets::minimum_balance(asset.clone()) + )); +} + +fn assert_last_event(generic_event: ::RuntimeEvent) { + let events = frame_system::Pallet::::events(); + let system_event: ::RuntimeEvent = generic_event.into(); + // compare to the last event record + let frame_system::EventRecord { event, .. } = &events[events.len() - 1]; + assert_eq!(event, &system_event); +} + +#[benchmarks(where T::Assets: Create + Mutate)] +mod benchmarks { + use super::*; + + #[benchmark] + fn create_pool() { + use super::*; + + let admin: T::AccountId = T::BenchmarkHelper::to_account_id(1); + let staked_asset = T::BenchmarkHelper::to_asset_id(0); + let reward_asset = T::BenchmarkHelper::to_asset_id(1); + create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); + create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + + #[extrinsic_call] + _( + SystemOrigin::Signed(admin.clone()), + Box::new(staked_asset.clone()), + Box::new(reward_asset.clone()), + 100u32.into(), + 200u32.into(), + None, + ); + + assert_last_event::( + Event::PoolCreated { + creator: admin.clone(), + admin, + staked_asset_id: staked_asset, + reward_asset_id: reward_asset, + reward_rate_per_block: 100u32.into(), + expiry_block: 200u32.into(), + pool_id: 0u32.into(), + } + .into(), + ); + } + + impl_benchmark_test_suite!(AssetRewards, crate::mock::new_test_ext(), crate::mock::MockRuntime); +} diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 81df78cbfed4..26e99ec09cf0 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -91,6 +91,8 @@ use sp_core::Get; use sp_runtime::DispatchError; use sp_std::boxed::Box; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; #[cfg(test)] mod mock; #[cfg(test)] @@ -125,7 +127,7 @@ pub struct PoolStakerInfo { #[derive(Debug, Clone, Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] pub struct PoolInfo { /// The asset that is staked in this pool. - staking_asset_id: AssetId, + staked_asset_id: AssetId, /// The asset that is distributed as rewards in this pool. reward_asset_id: AssetId, /// The amount of tokens distributed per block. @@ -144,7 +146,6 @@ pub struct PoolInfo { #[frame_support::pallet(dev_mode)] pub mod pallet { - use super::*; use frame_support::{ pallet_prelude::*, @@ -183,6 +184,13 @@ pub mod pallet { type Assets: Inspect + Mutate + Balanced; + + /// Weight information for extrinsics in this pallet. + // type WeightInfo: WeightInfo; + + /// The benchmarks need a way to create asset ids from u32s. + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper: benchmarking::BenchmarkHelper; } /// State of pool stakers. @@ -250,7 +258,7 @@ pub mod pallet { /// Unique ID for the new pool. pool_id: PoolId, /// The staking asset. - staking_asset_id: T::AssetId, + staked_asset_id: T::AssetId, /// The reward asset. reward_asset_id: T::AssetId, /// The initial reward rate per block. @@ -354,7 +362,7 @@ pub mod pallet { // Create the pool. let pool = PoolInfoFor:: { - staking_asset_id: *staked_asset_id.clone(), + staked_asset_id: *staked_asset_id.clone(), reward_asset_id: *reward_asset_id.clone(), reward_rate_per_block, total_tokens_staked: 0u32.into(), @@ -373,7 +381,7 @@ pub mod pallet { Self::deposit_event(Event::PoolCreated { creator: origin_acc_id, pool_id, - staking_asset_id: *staked_asset_id, + staked_asset_id: *staked_asset_id, reward_asset_id: *reward_asset_id, reward_rate_per_block, expiry_block, diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index c0f23bb33bff..25064d5a72e9 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -134,6 +134,8 @@ impl Config for MockRuntime { type Assets = NativeAndAssets; type PalletId = StakingRewardsPalletId; type PermissionedPoolCreator = MockPermissionedPoolCreator; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } pub(crate) fn new_test_ext() -> sp_io::TestExternalities { diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 90d8e11b89b1..99b954ddbaf9 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -28,11 +28,11 @@ use sp_runtime::{traits::BadOrigin, ArithmeticError, TokenError}; /// /// Useful to reduce boilerplate in tests when it's not important to customise or reusing pool /// params. -fn create_default_pool() { - let staking_asset_id = NativeOrWithId::::WithId(1); +pub fn create_default_pool() { + let staked_asset_id = NativeOrWithId::::WithId(1); assert_ok!(StakingRewards::create_pool( RuntimeOrigin::signed(1), - Box::new(staking_asset_id), + Box::new(staked_asset_id), Box::new(NativeOrWithId::::Native), 100, 100u64, @@ -93,7 +93,7 @@ mod create_pool { fn success() { new_test_ext().execute_with(|| { let user = 1; - let staking_asset_id = NativeOrWithId::::Native; + let staked_asset_id = NativeOrWithId::::Native; let reward_asset_id = NativeOrWithId::::WithId(1); let reward_rate_per_block = 100; let expiry_block = 200u64; @@ -101,7 +101,7 @@ mod create_pool { assert_eq!(NextPoolId::::get(), 0); assert_ok!(StakingRewards::create_pool( RuntimeOrigin::signed(user), - Box::new(staking_asset_id.clone()), + Box::new(staked_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, expiry_block, @@ -114,7 +114,7 @@ mod create_pool { [Event::::PoolCreated { creator: user, pool_id: 0, - staking_asset_id: staking_asset_id.clone(), + staked_asset_id: staked_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, expiry_block, @@ -129,7 +129,7 @@ mod create_pool { vec![( 0, PoolInfo { - staking_asset_id: staking_asset_id.clone(), + staked_asset_id: staked_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, expiry_block, @@ -145,7 +145,7 @@ mod create_pool { let admin = 2; assert_ok!(StakingRewards::create_pool( RuntimeOrigin::signed(user), - Box::new(staking_asset_id.clone()), + Box::new(staked_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, expiry_block, @@ -158,7 +158,7 @@ mod create_pool { [Event::::PoolCreated { creator: user, pool_id: 1, - staking_asset_id: staking_asset_id.clone(), + staked_asset_id: staked_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, admin, @@ -174,7 +174,7 @@ mod create_pool { ( 0, PoolInfo { - staking_asset_id: staking_asset_id.clone(), + staked_asset_id: staked_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, admin: user, @@ -187,7 +187,7 @@ mod create_pool { ( 1, PoolInfo { - staking_asset_id, + staked_asset_id, reward_asset_id, reward_rate_per_block, admin, @@ -250,14 +250,14 @@ mod create_pool { fn fails_for_not_admin() { new_test_ext().execute_with(|| { let user = 100; - let staking_asset_id = NativeOrWithId::::Native; + let staked_asset_id = NativeOrWithId::::Native; let reward_asset_id = NativeOrWithId::::WithId(1); let reward_rate_per_block = 100; let expiry_block = 100u64; assert_err!( StakingRewards::create_pool( RuntimeOrigin::signed(user), - Box::new(staking_asset_id.clone()), + Box::new(staked_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, expiry_block, @@ -272,7 +272,7 @@ mod create_pool { fn fails_for_bad_expiry_block() { new_test_ext().execute_with(|| { let user = 1; - let staking_asset_id = NativeOrWithId::::Native; + let staked_asset_id = NativeOrWithId::::Native; let reward_asset_id = NativeOrWithId::::WithId(1); let reward_rate_per_block = 100; let expiry_block = 100u64; @@ -280,7 +280,7 @@ mod create_pool { assert_err!( StakingRewards::create_pool( RuntimeOrigin::signed(user), - Box::new(staking_asset_id.clone()), + Box::new(staked_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, expiry_block, @@ -1032,13 +1032,13 @@ fn integration() { let admin = 1; let staker1 = 10u128; let staker2 = 20; - let staking_asset_id = NativeOrWithId::::WithId(1); + let staked_asset_id = NativeOrWithId::::WithId(1); let reward_asset_id = NativeOrWithId::::Native; let reward_rate_per_block = 100; let expiry_block = 25u64.into(); assert_ok!(StakingRewards::create_pool( RuntimeOrigin::signed(admin), - Box::new(staking_asset_id.clone()), + Box::new(staked_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, expiry_block, @@ -1170,7 +1170,7 @@ fn integration() { Event::PoolCreated { creator: admin, pool_id, - staking_asset_id, + staked_asset_id, reward_asset_id, reward_rate_per_block: 100, expiry_block: 25, From 1dfde3ff435195f487062e8cc8d59a942abfc35a Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sat, 6 Apr 2024 09:18:37 +0400 Subject: [PATCH 032/159] remove stub --- substrate/frame/asset-rewards/src/lib.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 26e99ec09cf0..492868dbe532 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -391,14 +391,6 @@ pub mod pallet { Ok(()) } - /// Removes an existing reward pool. - /// - /// TODO decide if we want to implement this functionality, and if so, how to manage clean - /// up of stakers from a removed pool. - pub fn remove_pool(_origin: OriginFor, _pool_id: PoolId) -> DispatchResult { - todo!() - } - /// Stake tokens in a pool. pub fn stake(origin: OriginFor, pool_id: PoolId, amount: T::Balance) -> DispatchResult { let caller = ensure_signed(origin)?; From 138fdbb9fde7ca7aa7bafbdb7482600958c05c9d Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sat, 6 Apr 2024 09:26:42 +0400 Subject: [PATCH 033/159] stake benchmark --- .../frame/asset-rewards/src/benchmarking.rs | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index d351bb059444..d4b51105559b 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -82,7 +82,7 @@ mod benchmarks { fn create_pool() { use super::*; - let admin: T::AccountId = T::BenchmarkHelper::to_account_id(1); + let admin = T::BenchmarkHelper::to_account_id(1); let staked_asset = T::BenchmarkHelper::to_asset_id(0); let reward_asset = T::BenchmarkHelper::to_asset_id(1); create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); @@ -112,5 +112,33 @@ mod benchmarks { ); } + #[benchmark] + fn stake() { + use super::*; + + let admin = T::BenchmarkHelper::to_account_id(1); + let staker = T::BenchmarkHelper::to_account_id(2); + let staked_asset = T::BenchmarkHelper::to_asset_id(0); + let reward_asset = T::BenchmarkHelper::to_asset_id(1); + create_asset::(&staker, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); + create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + + assert_ok!(AssetRewards::::create_pool( + SystemOrigin::Signed(admin.clone()).into(), + Box::new(staked_asset.clone()), + Box::new(reward_asset.clone()), + 100u32.into(), + 200u32.into(), + None, + )); + + #[extrinsic_call] + _(SystemOrigin::Signed(staker.clone()), 0u32.into(), 100u32.into()); + + assert_last_event::( + Event::Staked { who: staker, pool_id: 0u32.into(), amount: 100u32.into() }.into(), + ); + } + impl_benchmark_test_suite!(AssetRewards, crate::mock::new_test_ext(), crate::mock::MockRuntime); } From 159f63fcfa5a32e4fe66dd42d72c781cb4161916 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sat, 6 Apr 2024 09:29:22 +0400 Subject: [PATCH 034/159] unstake benchmark --- .../frame/asset-rewards/src/benchmarking.rs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index d4b51105559b..e78d213f026c 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -140,5 +140,39 @@ mod benchmarks { ); } + #[benchmark] + fn unstake() { + use super::*; + + let admin = T::BenchmarkHelper::to_account_id(1); + let staker = T::BenchmarkHelper::to_account_id(2); + let staked_asset = T::BenchmarkHelper::to_asset_id(0); + let reward_asset = T::BenchmarkHelper::to_asset_id(1); + create_asset::(&staker, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); + create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + + assert_ok!(AssetRewards::::create_pool( + SystemOrigin::Signed(admin.clone()).into(), + Box::new(staked_asset.clone()), + Box::new(reward_asset.clone()), + 100u32.into(), + 200u32.into(), + None, + )); + + assert_ok!(AssetRewards::::stake( + SystemOrigin::Signed(staker.clone()).into(), + 0u32.into(), + 100u32.into() + )); + + #[extrinsic_call] + _(SystemOrigin::Signed(staker.clone()), 0u32.into(), 100u32.into()); + + assert_last_event::( + Event::Unstaked { who: staker, pool_id: 0u32.into(), amount: 100u32.into() }.into(), + ); + } + impl_benchmark_test_suite!(AssetRewards, crate::mock::new_test_ext(), crate::mock::MockRuntime); } From 2fc9c0466785fe11223ddc17e254dce277dddeb3 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sat, 6 Apr 2024 09:37:02 +0400 Subject: [PATCH 035/159] harvest rewards benchmark --- .../frame/asset-rewards/src/benchmarking.rs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index e78d213f026c..2b49260954e8 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -174,5 +174,45 @@ mod benchmarks { ); } + #[benchmark] + fn harvest_rewards() { + use super::*; + + let admin = T::BenchmarkHelper::to_account_id(1); + let staker = T::BenchmarkHelper::to_account_id(2); + let staked_asset = T::BenchmarkHelper::to_asset_id(0); + let reward_asset = T::BenchmarkHelper::to_asset_id(1); + create_asset::(&staker, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); + create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + + assert_ok!(AssetRewards::::create_pool( + SystemOrigin::Signed(admin.clone()).into(), + Box::new(staked_asset.clone()), + Box::new(reward_asset.clone()), + 100u32.into(), + 200u32.into(), + None, + )); + + assert_ok!(AssetRewards::::stake( + SystemOrigin::Signed(staker.clone()).into(), + 0u32.into(), + 100u32.into() + )); + + #[extrinsic_call] + _(SystemOrigin::Signed(staker.clone()), 0u32.into(), None); + + assert_last_event::( + Event::RewardsHarvested { + who: staker.clone(), + staker, + pool_id: 0u32.into(), + amount: 0u32.into(), + } + .into(), + ); + } + impl_benchmark_test_suite!(AssetRewards, crate::mock::new_test_ext(), crate::mock::MockRuntime); } From d6cc5c2e4066654628d130c0fcdf223ac67eaaf7 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sat, 6 Apr 2024 09:38:45 +0400 Subject: [PATCH 036/159] set pool reward rate per block benchmark --- .../frame/asset-rewards/src/benchmarking.rs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 2b49260954e8..e00d4b658b3c 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -214,5 +214,36 @@ mod benchmarks { ); } + #[benchmark] + fn set_pool_reward_rate_per_block() { + use super::*; + + let admin = T::BenchmarkHelper::to_account_id(1); + let staked_asset = T::BenchmarkHelper::to_asset_id(0); + let reward_asset = T::BenchmarkHelper::to_asset_id(1); + create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); + create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + + assert_ok!(AssetRewards::::create_pool( + SystemOrigin::Signed(admin.clone()).into(), + Box::new(staked_asset.clone()), + Box::new(reward_asset.clone()), + 100u32.into(), + 200u32.into(), + None, + )); + + #[extrinsic_call] + _(SystemOrigin::Signed(admin.clone()), 0u32.into(), 5u32.into()); + + assert_last_event::( + Event::PoolRewardRateModified { + pool_id: 0u32.into(), + new_reward_rate_per_block: 5u32.into(), + } + .into(), + ); + } + impl_benchmark_test_suite!(AssetRewards, crate::mock::new_test_ext(), crate::mock::MockRuntime); } From b532b506e268064aa4074a30d73087cc6c7476e9 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sat, 6 Apr 2024 09:40:26 +0400 Subject: [PATCH 037/159] set pool admin benchmark --- .../frame/asset-rewards/src/benchmarking.rs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index e00d4b658b3c..d701a215846e 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -245,5 +245,31 @@ mod benchmarks { ); } + #[benchmark] + fn set_pool_admin() { + use super::*; + + let admin = T::BenchmarkHelper::to_account_id(1); + let new_admin = T::BenchmarkHelper::to_account_id(2); + let staked_asset = T::BenchmarkHelper::to_asset_id(0); + let reward_asset = T::BenchmarkHelper::to_asset_id(1); + create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); + create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + + assert_ok!(AssetRewards::::create_pool( + SystemOrigin::Signed(admin.clone()).into(), + Box::new(staked_asset.clone()), + Box::new(reward_asset.clone()), + 100u32.into(), + 200u32.into(), + None, + )); + + #[extrinsic_call] + _(SystemOrigin::Signed(admin.clone()), 0u32.into(), new_admin.clone()); + + assert_last_event::(Event::PoolAdminModified { pool_id: 0u32.into(), new_admin }.into()); + } + impl_benchmark_test_suite!(AssetRewards, crate::mock::new_test_ext(), crate::mock::MockRuntime); } From 898852c11782ae0a1f43fff1dd2b72ad388ecd02 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sat, 6 Apr 2024 09:41:46 +0400 Subject: [PATCH 038/159] benchmark set pool expiry block --- .../frame/asset-rewards/src/benchmarking.rs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index d701a215846e..6b563504fb68 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -271,5 +271,37 @@ mod benchmarks { assert_last_event::(Event::PoolAdminModified { pool_id: 0u32.into(), new_admin }.into()); } + #[benchmark] + fn set_pool_expiry_block() { + use super::*; + + let admin = T::BenchmarkHelper::to_account_id(1); + let new_admin = T::BenchmarkHelper::to_account_id(2); + let staked_asset = T::BenchmarkHelper::to_asset_id(0); + let reward_asset = T::BenchmarkHelper::to_asset_id(1); + create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); + create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + + assert_ok!(AssetRewards::::create_pool( + SystemOrigin::Signed(admin.clone()).into(), + Box::new(staked_asset.clone()), + Box::new(reward_asset.clone()), + 100u32.into(), + 200u32.into(), + None, + )); + + #[extrinsic_call] + _(SystemOrigin::Signed(admin.clone()), 0u32.into(), 1000u32.into()); + + assert_last_event::( + Event::PoolExpiryBlockModified { + pool_id: 0u32.into(), + new_expiry_block: 1000u32.into(), + } + .into(), + ); + } + impl_benchmark_test_suite!(AssetRewards, crate::mock::new_test_ext(), crate::mock::MockRuntime); } From 96ac58b42c00b93f4d5c27970270f13d14050c23 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sat, 6 Apr 2024 10:01:12 +0400 Subject: [PATCH 039/159] deposit reward tokens benchmark --- .../frame/asset-rewards/src/benchmarking.rs | 72 +++++++++++++------ 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 6b563504fb68..becc2819ce90 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -22,7 +22,10 @@ use crate::Pallet as AssetRewards; use frame_benchmarking::{v2::*, whitelisted_caller}; use frame_support::{ assert_ok, - traits::fungibles::{Create, Inspect, Mutate}, + traits::{ + fungible::NativeOrWithId, + fungibles::{Create, Inspect, Mutate}, + }, }; use frame_system::RawOrigin as SystemOrigin; use sp_runtime::traits::One; @@ -30,20 +33,18 @@ use sp_std::prelude::*; /// Benchmark Helper pub trait BenchmarkHelper { - /// Returns a valid assets pair for the pool creation. - /// /// When a specific asset, such as the native asset, is required in every pool, it should be /// returned for each odd-numbered seed. - fn to_asset_id(seed: u32) -> AssetId; + fn to_asset_id(seed: NativeOrWithId) -> AssetId; fn to_account_id(seed: u32) -> AccountId; } impl BenchmarkHelper for () where - AssetId: From, + AssetId: From>, AccountId: From, { - fn to_asset_id(seed: u32) -> AssetId { + fn to_asset_id(seed: NativeOrWithId) -> AssetId { seed.into() } fn to_account_id(seed: u32) -> AccountId { @@ -83,8 +84,8 @@ mod benchmarks { use super::*; let admin = T::BenchmarkHelper::to_account_id(1); - let staked_asset = T::BenchmarkHelper::to_asset_id(0); - let reward_asset = T::BenchmarkHelper::to_asset_id(1); + let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); + let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); @@ -118,8 +119,8 @@ mod benchmarks { let admin = T::BenchmarkHelper::to_account_id(1); let staker = T::BenchmarkHelper::to_account_id(2); - let staked_asset = T::BenchmarkHelper::to_asset_id(0); - let reward_asset = T::BenchmarkHelper::to_asset_id(1); + let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); + let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&staker, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); @@ -146,8 +147,8 @@ mod benchmarks { let admin = T::BenchmarkHelper::to_account_id(1); let staker = T::BenchmarkHelper::to_account_id(2); - let staked_asset = T::BenchmarkHelper::to_asset_id(0); - let reward_asset = T::BenchmarkHelper::to_asset_id(1); + let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); + let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&staker, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); @@ -180,8 +181,8 @@ mod benchmarks { let admin = T::BenchmarkHelper::to_account_id(1); let staker = T::BenchmarkHelper::to_account_id(2); - let staked_asset = T::BenchmarkHelper::to_asset_id(0); - let reward_asset = T::BenchmarkHelper::to_asset_id(1); + let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); + let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&staker, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); @@ -219,8 +220,8 @@ mod benchmarks { use super::*; let admin = T::BenchmarkHelper::to_account_id(1); - let staked_asset = T::BenchmarkHelper::to_asset_id(0); - let reward_asset = T::BenchmarkHelper::to_asset_id(1); + let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); + let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); @@ -251,8 +252,8 @@ mod benchmarks { let admin = T::BenchmarkHelper::to_account_id(1); let new_admin = T::BenchmarkHelper::to_account_id(2); - let staked_asset = T::BenchmarkHelper::to_asset_id(0); - let reward_asset = T::BenchmarkHelper::to_asset_id(1); + let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); + let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); @@ -276,9 +277,8 @@ mod benchmarks { use super::*; let admin = T::BenchmarkHelper::to_account_id(1); - let new_admin = T::BenchmarkHelper::to_account_id(2); - let staked_asset = T::BenchmarkHelper::to_asset_id(0); - let reward_asset = T::BenchmarkHelper::to_asset_id(1); + let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); + let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); @@ -303,5 +303,35 @@ mod benchmarks { ); } + #[benchmark] + fn deposit_reward_tokens() { + use super::*; + + let admin = T::BenchmarkHelper::to_account_id(1); + let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); + let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); + create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); + create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + + T::Assets::set_balance(reward_asset.clone(), &admin, 100000u32.into()); + assert_ok!(AssetRewards::::create_pool( + SystemOrigin::Signed(admin.clone()).into(), + Box::new(staked_asset.clone()), + Box::new(reward_asset.clone()), + 100u32.into(), + 200u32.into(), + None, + )); + + let balance_before = T::Assets::balance(reward_asset.clone(), &admin); + + #[extrinsic_call] + _(SystemOrigin::Signed(admin.clone()), 0u32.into(), 10u32.into()); + + let balance_after = T::Assets::balance(reward_asset.clone(), &admin); + + assert_eq!(balance_after, balance_before - 10u32.into()); + } + impl_benchmark_test_suite!(AssetRewards, crate::mock::new_test_ext(), crate::mock::MockRuntime); } From d2ef188981965f7361191523ab52cd1258bd58b3 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sat, 6 Apr 2024 10:02:53 +0400 Subject: [PATCH 040/159] withdraw reward tokens benchmark --- .../frame/asset-rewards/src/benchmarking.rs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index becc2819ce90..362c1ea19011 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -333,5 +333,42 @@ mod benchmarks { assert_eq!(balance_after, balance_before - 10u32.into()); } + #[benchmark] + fn withdraw_reward_tokens() { + use super::*; + + let admin = T::BenchmarkHelper::to_account_id(1); + let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); + let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); + create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); + create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + + T::Assets::set_balance(reward_asset.clone(), &admin, 100000u32.into()); + assert_ok!(AssetRewards::::create_pool( + SystemOrigin::Signed(admin.clone()).into(), + Box::new(staked_asset.clone()), + Box::new(reward_asset.clone()), + 100u32.into(), + 200u32.into(), + None, + )); + + let balance_before = T::Assets::balance(reward_asset.clone(), &admin); + + assert_ok!(AssetRewards::::deposit_reward_tokens( + SystemOrigin::Signed(admin.clone()).into(), + 0u32.into(), + 10u32.into() + )); + + #[extrinsic_call] + _(SystemOrigin::Signed(admin.clone()), 0u32.into(), 5u32.into()); + + let balance_after = T::Assets::balance(reward_asset.clone(), &admin); + + // Deposited 10, withdrew 5 + assert_eq!(balance_after, balance_before - 5u32.into()); + } + impl_benchmark_test_suite!(AssetRewards, crate::mock::new_test_ext(), crate::mock::MockRuntime); } From 5c8185a269ba6c2c2dc85515d3775821e8bf6cc3 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sat, 6 Apr 2024 10:03:37 +0400 Subject: [PATCH 041/159] remove unused import --- substrate/frame/asset-rewards/src/benchmarking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 362c1ea19011..b91084a61c0f 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -19,7 +19,7 @@ use super::*; use crate::Pallet as AssetRewards; -use frame_benchmarking::{v2::*, whitelisted_caller}; +use frame_benchmarking::v2::*; use frame_support::{ assert_ok, traits::{ From 15ced21985e06e8bee1e852c5763581686cd6010 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sat, 6 Apr 2024 10:05:42 +0400 Subject: [PATCH 042/159] reduce code duplication --- substrate/frame/asset-rewards/src/lib.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 492868dbe532..b1af28477197 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -628,16 +628,13 @@ pub mod pallet { /// NOTE: this is a pure function without side effects. It does not modify any state /// directly, that is the responsibility of the caller. pub fn update_pool_and_staker_rewards( - mut pool_info: PoolInfoFor, + pool_info: PoolInfoFor, mut staker_info: PoolStakerInfo, ) -> Result<(PoolInfoFor, PoolStakerInfo), DispatchError> { - let reward_per_token = Self::reward_per_token(&pool_info)?; - - pool_info.last_update_block = frame_system::Pallet::::block_number(); - pool_info.reward_per_token_stored = reward_per_token; + let pool_info = Self::update_pool_rewards(pool_info)?; staker_info.rewards = Self::derive_rewards(&pool_info, &staker_info)?; - staker_info.reward_per_token_paid = reward_per_token; + staker_info.reward_per_token_paid = pool_info.reward_per_token_stored; return Ok((pool_info, staker_info)); } From 12257da3b107574604b9f1cb69bce99d5912434b Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sat, 6 Apr 2024 10:13:52 +0400 Subject: [PATCH 043/159] commit empty weights file --- substrate/frame/asset-rewards/src/weights.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 substrate/frame/asset-rewards/src/weights.rs diff --git a/substrate/frame/asset-rewards/src/weights.rs b/substrate/frame/asset-rewards/src/weights.rs new file mode 100644 index 000000000000..e69de29bb2d1 From e1eb1d6587912cd20d2aabde215e0a90e5238cce Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Sun, 7 Apr 2024 11:00:16 +0400 Subject: [PATCH 044/159] integration into kitchensink --- Cargo.lock | 1 + substrate/bin/node/runtime/Cargo.toml | 4 ++ substrate/bin/node/runtime/src/lib.rs | 45 ++++++++++++ .../frame/asset-rewards/src/benchmarking.rs | 69 ++++++++++--------- substrate/frame/asset-rewards/src/lib.rs | 2 +- 5 files changed, 88 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3bbda3c8548a..f4f66e92be5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7033,6 +7033,7 @@ dependencies = [ "pallet-asset-conversion", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", + "pallet-asset-rewards", "pallet-asset-tx-payment", "pallet-assets", "pallet-authority-discovery", diff --git a/substrate/bin/node/runtime/Cargo.toml b/substrate/bin/node/runtime/Cargo.toml index f4ed75b91964..0257f68a7bd1 100644 --- a/substrate/bin/node/runtime/Cargo.toml +++ b/substrate/bin/node/runtime/Cargo.toml @@ -66,6 +66,7 @@ frame-system-rpc-runtime-api = { path = "../../../frame/system/rpc/runtime-api", frame-try-runtime = { path = "../../../frame/try-runtime", default-features = false, optional = true } pallet-alliance = { path = "../../../frame/alliance", default-features = false } pallet-asset-conversion = { path = "../../../frame/asset-conversion", default-features = false } +pallet-asset-rewards = { path = "../../../frame/asset-rewards", default-features = false } pallet-asset-rate = { path = "../../../frame/asset-rate", default-features = false } pallet-assets = { path = "../../../frame/assets", default-features = false } pallet-authority-discovery = { path = "../../../frame/authority-discovery", default-features = false } @@ -269,6 +270,7 @@ std = [ "sp-transaction-pool/std", "sp-version/std", "substrate-wasm-builder", + "pallet-asset-rewards/std" ] runtime-benchmarks = [ "frame-benchmarking-pallet-pov/runtime-benchmarks", @@ -345,6 +347,7 @@ runtime-benchmarks = [ "pallet-whitelist/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "sp-staking/runtime-benchmarks", + "pallet-asset-rewards/runtime-benchmarks" ] try-runtime = [ "frame-benchmarking-pallet-pov/try-runtime", @@ -426,6 +429,7 @@ try-runtime = [ "pallet-vesting/try-runtime", "pallet-whitelist/try-runtime", "sp-runtime/try-runtime", + "pallet-asset-rewards/try-runtime" ] experimental = [ "frame-support/experimental", diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 09326de27328..ff949bdb897f 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -71,11 +71,13 @@ use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use pallet_nfts::PalletFeatures; use pallet_nis::WithMaximumOf; use pallet_session::historical as pallet_session_historical; +use sp_core::TypedGet; // Can't use `FungibleAdapter` here until Treasury pallet migrates to fungibles // #[allow(deprecated)] pub use pallet_transaction_payment::{CurrencyAdapter, Multiplier, TargetedFeeAdjustment}; use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; +use pallet_treasury::TreasuryAccountId; use pallet_tx_pause::RuntimeCallNameOf; use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; @@ -1723,6 +1725,45 @@ impl pallet_asset_conversion::Config for Runtime { type BenchmarkHelper = (); } +pub type NativeAndAssets = + UnionOf, AccountId>; + +parameter_types! { + pub const StakingRewardsPalletId: PalletId = PalletId(*b"py/stkrd"); +} + +/// Benchmark Helper +#[cfg(feature = "runtime-benchmarks")] +pub struct AssetRewardsBenchmarkHelper; + +#[cfg(feature = "runtime-benchmarks")] +impl pallet_asset_rewards::benchmarking::BenchmarkHelper, AccountId> + for AssetRewardsBenchmarkHelper +{ + fn to_asset_id(seed: NativeOrWithId) -> NativeOrWithId { + seed + } + fn to_account_id(seed: u32) -> AccountId { + let mut bytes = [0u8; 32]; // Create a 32-byte array filled with zeros + bytes[0..4].copy_from_slice(&seed.to_be_bytes()); // Place the u32 value at the beginning (big-endian for this example) + bytes.into() + } + fn permissioned_pool_creator() -> AccountId { + TreasuryAccountId::::get() + } +} + +impl pallet_asset_rewards::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type AssetId = NativeOrWithId; + type Balance = u128; + type Assets = NativeAndAssets; + type PalletId = StakingRewardsPalletId; + type PermissionedPoolCreator = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = AssetRewardsBenchmarkHelper; +} + parameter_types! { pub const QueueCount: u32 = 300; pub const MaxQueueLen: u32 = 1000; @@ -2450,6 +2491,9 @@ mod runtime { #[runtime::pallet_index(78)] pub type PalletExampleMbms = pallet_example_mbm; + + #[runtime::pallet_index(79)] + pub type AssetRewards = pallet_asset_rewards; } /// The address format for describing accounts. @@ -2562,6 +2606,7 @@ mod benches { [tasks_example, TasksExample] [pallet_democracy, Democracy] [pallet_asset_conversion, AssetConversion] + [pallet_asset_rewards, AssetRewards] [pallet_election_provider_multi_phase, ElectionProviderMultiPhase] [pallet_election_provider_support_benchmarking, EPSBench::] [pallet_elections_phragmen, Elections] diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index b91084a61c0f..3b50e718d34d 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -27,16 +27,18 @@ use frame_support::{ fungibles::{Create, Inspect, Mutate}, }, }; -use frame_system::RawOrigin as SystemOrigin; +use frame_system::RawOrigin; use sp_runtime::traits::One; use sp_std::prelude::*; /// Benchmark Helper pub trait BenchmarkHelper { - /// When a specific asset, such as the native asset, is required in every pool, it should be - /// returned for each odd-numbered seed. + /// Convert a NativeOrWithId to an AssetId fn to_asset_id(seed: NativeOrWithId) -> AssetId; + /// Convert a u32 to an AccountId fn to_account_id(seed: u32) -> AccountId; + /// Get the permissioned pool creator + fn permissioned_pool_creator() -> AccountId; } impl BenchmarkHelper for () @@ -50,6 +52,9 @@ where fn to_account_id(seed: u32) -> AccountId { seed.into() } + fn permissioned_pool_creator() -> AccountId { + 1u32.into() + } } /// Create the `asset` and mint the `amount` for the `caller`. @@ -83,7 +88,7 @@ mod benchmarks { fn create_pool() { use super::*; - let admin = T::BenchmarkHelper::to_account_id(1); + let admin = T::BenchmarkHelper::permissioned_pool_creator(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); @@ -91,7 +96,7 @@ mod benchmarks { #[extrinsic_call] _( - SystemOrigin::Signed(admin.clone()), + RawOrigin::Signed(admin.clone()), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -117,7 +122,7 @@ mod benchmarks { fn stake() { use super::*; - let admin = T::BenchmarkHelper::to_account_id(1); + let admin = T::BenchmarkHelper::permissioned_pool_creator(); let staker = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); @@ -125,7 +130,7 @@ mod benchmarks { create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); assert_ok!(AssetRewards::::create_pool( - SystemOrigin::Signed(admin.clone()).into(), + RawOrigin::Signed(admin.clone()).into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -134,7 +139,7 @@ mod benchmarks { )); #[extrinsic_call] - _(SystemOrigin::Signed(staker.clone()), 0u32.into(), 100u32.into()); + _(RawOrigin::Signed(staker.clone()), 0u32.into(), 100u32.into()); assert_last_event::( Event::Staked { who: staker, pool_id: 0u32.into(), amount: 100u32.into() }.into(), @@ -145,7 +150,7 @@ mod benchmarks { fn unstake() { use super::*; - let admin = T::BenchmarkHelper::to_account_id(1); + let admin = T::BenchmarkHelper::permissioned_pool_creator(); let staker = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); @@ -153,7 +158,7 @@ mod benchmarks { create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); assert_ok!(AssetRewards::::create_pool( - SystemOrigin::Signed(admin.clone()).into(), + RawOrigin::Signed(admin.clone()).into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -162,13 +167,13 @@ mod benchmarks { )); assert_ok!(AssetRewards::::stake( - SystemOrigin::Signed(staker.clone()).into(), + RawOrigin::Signed(staker.clone()).into(), 0u32.into(), 100u32.into() )); #[extrinsic_call] - _(SystemOrigin::Signed(staker.clone()), 0u32.into(), 100u32.into()); + _(RawOrigin::Signed(staker.clone()), 0u32.into(), 100u32.into()); assert_last_event::( Event::Unstaked { who: staker, pool_id: 0u32.into(), amount: 100u32.into() }.into(), @@ -179,7 +184,7 @@ mod benchmarks { fn harvest_rewards() { use super::*; - let admin = T::BenchmarkHelper::to_account_id(1); + let admin = T::BenchmarkHelper::permissioned_pool_creator(); let staker = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); @@ -187,7 +192,7 @@ mod benchmarks { create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); assert_ok!(AssetRewards::::create_pool( - SystemOrigin::Signed(admin.clone()).into(), + RawOrigin::Signed(admin.clone()).into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -196,13 +201,13 @@ mod benchmarks { )); assert_ok!(AssetRewards::::stake( - SystemOrigin::Signed(staker.clone()).into(), + RawOrigin::Signed(staker.clone()).into(), 0u32.into(), 100u32.into() )); #[extrinsic_call] - _(SystemOrigin::Signed(staker.clone()), 0u32.into(), None); + _(RawOrigin::Signed(staker.clone()), 0u32.into(), None); assert_last_event::( Event::RewardsHarvested { @@ -219,14 +224,14 @@ mod benchmarks { fn set_pool_reward_rate_per_block() { use super::*; - let admin = T::BenchmarkHelper::to_account_id(1); + let admin = T::BenchmarkHelper::permissioned_pool_creator(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); assert_ok!(AssetRewards::::create_pool( - SystemOrigin::Signed(admin.clone()).into(), + RawOrigin::Signed(admin.clone()).into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -235,7 +240,7 @@ mod benchmarks { )); #[extrinsic_call] - _(SystemOrigin::Signed(admin.clone()), 0u32.into(), 5u32.into()); + _(RawOrigin::Signed(admin.clone()), 0u32.into(), 5u32.into()); assert_last_event::( Event::PoolRewardRateModified { @@ -250,7 +255,7 @@ mod benchmarks { fn set_pool_admin() { use super::*; - let admin = T::BenchmarkHelper::to_account_id(1); + let admin = T::BenchmarkHelper::permissioned_pool_creator(); let new_admin = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); @@ -258,7 +263,7 @@ mod benchmarks { create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); assert_ok!(AssetRewards::::create_pool( - SystemOrigin::Signed(admin.clone()).into(), + RawOrigin::Signed(admin.clone()).into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -267,7 +272,7 @@ mod benchmarks { )); #[extrinsic_call] - _(SystemOrigin::Signed(admin.clone()), 0u32.into(), new_admin.clone()); + _(RawOrigin::Signed(admin.clone()), 0u32.into(), new_admin.clone()); assert_last_event::(Event::PoolAdminModified { pool_id: 0u32.into(), new_admin }.into()); } @@ -276,14 +281,14 @@ mod benchmarks { fn set_pool_expiry_block() { use super::*; - let admin = T::BenchmarkHelper::to_account_id(1); + let admin = T::BenchmarkHelper::permissioned_pool_creator(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); assert_ok!(AssetRewards::::create_pool( - SystemOrigin::Signed(admin.clone()).into(), + RawOrigin::Signed(admin.clone()).into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -292,7 +297,7 @@ mod benchmarks { )); #[extrinsic_call] - _(SystemOrigin::Signed(admin.clone()), 0u32.into(), 1000u32.into()); + _(RawOrigin::Signed(admin.clone()), 0u32.into(), 1000u32.into()); assert_last_event::( Event::PoolExpiryBlockModified { @@ -307,7 +312,7 @@ mod benchmarks { fn deposit_reward_tokens() { use super::*; - let admin = T::BenchmarkHelper::to_account_id(1); + let admin = T::BenchmarkHelper::permissioned_pool_creator(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); @@ -315,7 +320,7 @@ mod benchmarks { T::Assets::set_balance(reward_asset.clone(), &admin, 100000u32.into()); assert_ok!(AssetRewards::::create_pool( - SystemOrigin::Signed(admin.clone()).into(), + RawOrigin::Signed(admin.clone()).into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -326,7 +331,7 @@ mod benchmarks { let balance_before = T::Assets::balance(reward_asset.clone(), &admin); #[extrinsic_call] - _(SystemOrigin::Signed(admin.clone()), 0u32.into(), 10u32.into()); + _(RawOrigin::Signed(admin.clone()), 0u32.into(), 10u32.into()); let balance_after = T::Assets::balance(reward_asset.clone(), &admin); @@ -337,7 +342,7 @@ mod benchmarks { fn withdraw_reward_tokens() { use super::*; - let admin = T::BenchmarkHelper::to_account_id(1); + let admin = T::BenchmarkHelper::permissioned_pool_creator(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); @@ -345,7 +350,7 @@ mod benchmarks { T::Assets::set_balance(reward_asset.clone(), &admin, 100000u32.into()); assert_ok!(AssetRewards::::create_pool( - SystemOrigin::Signed(admin.clone()).into(), + RawOrigin::Signed(admin.clone()).into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -356,13 +361,13 @@ mod benchmarks { let balance_before = T::Assets::balance(reward_asset.clone(), &admin); assert_ok!(AssetRewards::::deposit_reward_tokens( - SystemOrigin::Signed(admin.clone()).into(), + RawOrigin::Signed(admin.clone()).into(), 0u32.into(), 10u32.into() )); #[extrinsic_call] - _(SystemOrigin::Signed(admin.clone()), 0u32.into(), 5u32.into()); + _(RawOrigin::Signed(admin.clone()), 0u32.into(), 5u32.into()); let balance_after = T::Assets::balance(reward_asset.clone(), &admin); diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index b1af28477197..9f1c9083dfc3 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -92,7 +92,7 @@ use sp_runtime::DispatchError; use sp_std::boxed::Box; #[cfg(feature = "runtime-benchmarks")] -mod benchmarking; +pub mod benchmarking; #[cfg(test)] mod mock; #[cfg(test)] From 48a70ebe23de0f5ed83d5c098a988c14d4f953ca Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 10 Apr 2024 10:01:04 +0400 Subject: [PATCH 045/159] remove unnecesary bound --- substrate/frame/asset-rewards/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 9f1c9083dfc3..0e2ebea072ea 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -81,7 +81,7 @@ pub use pallet::*; use frame_support::{ traits::{ - fungibles::{Balanced, Inspect, Mutate}, + fungibles::{Inspect, Mutate}, tokens::Balance, }, PalletId, @@ -182,8 +182,7 @@ pub mod pallet { /// Registry of assets that can be configured to either stake for rewards, or be offered as /// rewards for staking. type Assets: Inspect - + Mutate - + Balanced; + + Mutate; /// Weight information for extrinsics in this pallet. // type WeightInfo: WeightInfo; From b190e478e25bfa5e310a3f141771a8264235d4f6 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 10 Apr 2024 10:03:40 +0400 Subject: [PATCH 046/159] rococo set up reward pallet assets --- Cargo.lock | 1 + .../assets/asset-hub-rococo/Cargo.toml | 1 + .../assets/asset-hub-rococo/src/lib.rs | 42 ++++++++++++++++--- .../assets/asset-hub-rococo/src/xcm_config.rs | 4 +- .../runtimes/assets/common/src/lib.rs | 10 ++++- 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9fad4eb0f1d..2fdb0ae00155 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -866,6 +866,7 @@ dependencies = [ "log", "pallet-asset-conversion", "pallet-asset-conversion-tx-payment", + "pallet-asset-rewards", "pallet-assets", "pallet-aura", "pallet-authorship", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml index 0733156716c1..c2090d102a56 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml @@ -26,6 +26,7 @@ frame-try-runtime = { path = "../../../../../substrate/frame/try-runtime", defau pallet-asset-conversion-tx-payment = { path = "../../../../../substrate/frame/transaction-payment/asset-conversion-tx-payment", default-features = false } pallet-assets = { path = "../../../../../substrate/frame/assets", default-features = false } pallet-asset-conversion = { path = "../../../../../substrate/frame/asset-conversion", default-features = false } +pallet-asset-rewards = { path = "../../../../../substrate/frame/asset-rewards", default-features = false } pallet-aura = { path = "../../../../../substrate/frame/aura", default-features = false } pallet-authorship = { path = "../../../../../substrate/frame/authorship", default-features = false } pallet-balances = { path = "../../../../../substrate/frame/balances", default-features = false } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 9e21d1133237..df8505a94649 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -31,6 +31,7 @@ use assets_common::{ foreign_creators::ForeignCreators, local_and_foreign_assets::{LocalFromLeft, TargetFromLeft}, matching::{FromNetwork, FromSiblingParachain}, + AssetIdForPoolAssets, AssetIdForPoolAssetsConvertV3Location, AssetIdForTrustBackedAssetsConvert, }; use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; @@ -81,7 +82,7 @@ use sp_runtime::{Perbill, RuntimeDebug}; use testnet_parachains_constants::rococo::{consensus::*, currency::*, fee::WeightToFee, time::*}; use xcm_config::{ ForeignAssetsConvertedConcreteId, ForeignCreatorsSovereignAccountOf, GovernanceLocation, - PoolAssetsConvertedConcreteId, TokenLocation, TokenLocationV3, + PoolAssetsConvertedConcreteId, PoolAssetsPalletLocationV3, TokenLocation, TokenLocationV3, TrustBackedAssetsConvertedConcreteId, TrustBackedAssetsPalletLocationV3, }; @@ -290,7 +291,7 @@ impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type RemoveItemsLimit = ConstU32<1000>; - type AssetId = u32; + type AssetId = AssetIdForPoolAssets; type AssetIdParameter = u32; type Currency = Balances; type CreateOrigin = @@ -324,8 +325,8 @@ pub type LocalAndForeignAssets = fungibles::UnionOf< AccountId, >; -/// Union fungibles implementation for [`LocalAndForeignAssets`] and `Balances`. -pub type NativeAndAssets = fungible::UnionOf< +/// Union fungibles implementation for [`LocalAndForeignAssets`] and [`Balances`]. +pub type NativeAndNonPoolAssets = fungible::UnionOf< Balances, LocalAndForeignAssets, TargetFromLeft, @@ -333,12 +334,27 @@ pub type NativeAndAssets = fungible::UnionOf< AccountId, >; +/// Union fungibles implementation for [`PoolAssets`] and [`NativeAndAssets`]. +/// +/// Should be kept updated to include ALL balances and assets in the runtime. +pub type NativeAndAllAssets = fungibles::UnionOf< + PoolAssets, + NativeAndNonPoolAssets, + LocalFromLeft< + AssetIdForPoolAssetsConvertV3Location, + AssetIdForPoolAssets, + xcm::v3::Location, + >, + xcm::v3::Location, + AccountId, +>; + impl pallet_asset_conversion::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type HigherPrecisionBalance = sp_core::U256; type AssetKind = xcm::v3::Location; - type Assets = NativeAndAssets; + type Assets = NativeAndNonPoolAssets; type PoolId = (Self::AssetKind, Self::AssetKind); type PoolLocator = pallet_asset_conversion::WithFirstAsset; @@ -887,6 +903,21 @@ impl pallet_xcm_bridge_hub_router::Config for Runtim type FeeAsset = xcm_config::bridging::XcmBridgeHubRouterFeeAssetId; } +parameter_types! { + pub const AssetRewardsPalletId: PalletId = PalletId(*b"py/asrwd"); +} + +impl pallet_asset_rewards::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type PalletId = AssetRewardsPalletId; + type Balance = Balance; + type Assets = NativeAndAllAssets; + type AssetId = xcm::v3::Location; + type PermissionedPoolCreator = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -931,6 +962,7 @@ construct_runtime!( NftFractionalization: pallet_nft_fractionalization = 54, PoolAssets: pallet_assets:: = 55, AssetConversion: pallet_asset_conversion = 56, + AssetRewards: pallet_asset_rewards = 57, #[cfg(feature = "state-trie-version-1")] StateTrieMigration: pallet_state_trie_migration = 70, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 1c58abcb379e..598c058cb283 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -579,12 +579,12 @@ impl xcm_executor::Config for XcmConfig { TokenLocationV3, crate::AssetConversion, WeightToFee, - crate::NativeAndAssets, + crate::NativeAndNonPoolAssets, ( TrustBackedAssetsAsLocation, ForeignAssetsConvertedConcreteId, ), - ResolveAssetTo, + ResolveAssetTo, AccountId, >, // This trader allows to pay with `is_sufficient=true` "Trust Backed" assets from dedicated diff --git a/cumulus/parachains/runtimes/assets/common/src/lib.rs b/cumulus/parachains/runtimes/assets/common/src/lib.rs index fa2752179eb6..85e8ab15bab5 100644 --- a/cumulus/parachains/runtimes/assets/common/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/common/src/lib.rs @@ -111,7 +111,15 @@ pub type ForeignAssetsConvertedConcreteId; -type AssetIdForPoolAssets = u32; +pub type AssetIdForPoolAssets = u32; +/// `Location` vs `AssetIdForPoolAssets` converter for `PoolAssets` with explicit `v3 Location`. +pub type AssetIdForPoolAssetsConvertV3Location = AsPrefixedGeneralIndex< + PoolAssetsPalletLocation, + AssetIdForPoolAssets, + JustTry, + xcm::v3::Location, +>; + /// `Location` vs `AssetIdForPoolAssets` converter for `PoolAssets`. pub type AssetIdForPoolAssetsConvert = AsPrefixedGeneralIndex; From 2d196c22eaeb8e1d7a49445a03ac202ad0f83b6d Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 10 Apr 2024 10:14:39 +0400 Subject: [PATCH 047/159] configure permissioned pool creator origin --- .../parachains/runtimes/assets/asset-hub-rococo/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index df8505a94649..22687addb57c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -905,6 +905,7 @@ impl pallet_xcm_bridge_hub_router::Config for Runtim parameter_types! { pub const AssetRewardsPalletId: PalletId = PalletId(*b"py/asrwd"); + pub const TreasurerBodyId: BodyId = BodyId::Treasury; } impl pallet_asset_rewards::Config for Runtime { @@ -913,7 +914,10 @@ impl pallet_asset_rewards::Config for Runtime { type Balance = Balance; type Assets = NativeAndAllAssets; type AssetId = xcm::v3::Location; - type PermissionedPoolCreator = EnsureRoot; + type PermissionedPoolCreator = EitherOfDiverse< + EnsureRoot, + EnsureXcm>, + >; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); } From 57b17279d241134ef7eb7e597e09ec2b1b2a2bea Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 10 Apr 2024 15:22:39 +0400 Subject: [PATCH 048/159] refactor origin success accountid --- substrate/bin/node/runtime/src/lib.rs | 2 +- substrate/frame/asset-rewards/src/lib.rs | 47 ++-- substrate/frame/asset-rewards/src/mock.rs | 40 ++- substrate/frame/asset-rewards/src/tests.rs | 298 +++++++++++++++------ 4 files changed, 266 insertions(+), 121 deletions(-) diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 30de982a437a..c6000710c5c7 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1763,7 +1763,7 @@ impl pallet_asset_rewards::Config for Runtime { type Balance = u128; type Assets = NativeAndAssets; type PalletId = StakingRewardsPalletId; - type PermissionedPoolCreator = EnsureRoot; + type PermissionedOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = AssetRewardsBenchmarkHelper; } diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 0e2ebea072ea..424e0b0d87be 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -177,7 +177,10 @@ pub mod pallet { /// The origin with permission to create pools. This will be removed in a later release of /// this pallet, which will allow permissionless pool creation. - type PermissionedPoolCreator: EnsureOrigin; + /// + /// The Origin must return an AccountId. This can be achieved for any Origin by wrapping it + /// with `EnsureSuccess`. + type PermissionedOrigin: EnsureOrigin; /// Registry of assets that can be configured to either stake for rewards, or be offered as /// rewards for staking. @@ -333,8 +336,8 @@ pub mod pallet { expiry_block: BlockNumberFor, admin: Option, ) -> DispatchResult { - // Ensure Origin is allowed to create pools. - T::PermissionedPoolCreator::ensure_origin(origin.clone())?; + // Check the origin. + let creator = T::PermissionedOrigin::ensure_origin(origin.clone())?; // Ensure the assets exist. ensure!( @@ -353,11 +356,7 @@ pub mod pallet { ); // Get the admin, defaulting to the origin. - let origin_acc_id = ensure_signed(origin)?; - let admin = match admin { - Some(admin) => admin, - None => origin_acc_id.clone(), - }; + let admin = admin.unwrap_or(creator.clone()); // Create the pool. let pool = PoolInfoFor:: { @@ -378,7 +377,7 @@ pub mod pallet { // Emit created event. Self::deposit_event(Event::PoolCreated { - creator: origin_acc_id, + creator, pool_id, staked_asset_id: *staked_asset_id, reward_asset_id: *reward_asset_id, @@ -459,10 +458,7 @@ pub mod pallet { ) -> DispatchResult { let caller = ensure_signed(origin)?; - let staker = match staker { - Some(staker) => staker, - None => caller.clone(), - }; + let staker = staker.unwrap_or(caller.clone()); // Always start by updating the pool and staker rewards. let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; @@ -502,9 +498,11 @@ pub mod pallet { pool_id: PoolId, new_reward_rate_per_block: T::Balance, ) -> DispatchResult { - let caller = ensure_signed(origin)?; + let caller = T::PermissionedOrigin::ensure_origin(origin.clone()) + .or_else(|_| ensure_signed(origin))?; + let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin == caller, BadOrigin); + ensure!(caller == pool_info.admin, BadOrigin); // Always start by updating the pool rewards. let mut pool_info = Self::update_pool_rewards(pool_info)?; @@ -526,7 +524,8 @@ pub mod pallet { pool_id: PoolId, new_admin: T::AccountId, ) -> DispatchResult { - let caller = ensure_signed(origin)?; + let caller = T::PermissionedOrigin::ensure_origin(origin.clone()) + .or_else(|_| ensure_signed(origin))?; let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; ensure!(pool_info.admin == caller, BadOrigin); @@ -544,7 +543,8 @@ pub mod pallet { pool_id: PoolId, new_expiry_block: BlockNumberFor, ) -> DispatchResult { - let caller = ensure_signed(origin)?; + let caller = T::PermissionedOrigin::ensure_origin(origin.clone()) + .or_else(|_| ensure_signed(origin))?; ensure!( new_expiry_block > frame_system::Pallet::::block_number(), @@ -592,14 +592,17 @@ pub mod pallet { origin: OriginFor, pool_id: PoolId, amount: T::Balance, + dest: T::AccountId, ) -> DispatchResult { - let caller = ensure_signed(origin)?; + let caller = T::PermissionedOrigin::ensure_origin(origin.clone()) + .or_else(|_| ensure_signed(origin))?; + let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; ensure!(pool_info.admin == caller, BadOrigin); T::Assets::transfer( pool_info.reward_asset_id, &Self::pool_account_id(&pool_id)?, - &caller, + &dest, amount, Preservation::Preserve, )?; @@ -624,8 +627,7 @@ pub mod pallet { /// /// Returns the updated pool and staker info. /// - /// NOTE: this is a pure function without side effects. It does not modify any state - /// directly, that is the responsibility of the caller. + /// NOTE: does not modify any storage, that is the responsibility of the caller. pub fn update_pool_and_staker_rewards( pool_info: PoolInfoFor, mut staker_info: PoolStakerInfo, @@ -643,8 +645,7 @@ pub mod pallet { /// /// Returns the updated pool and staker info. /// - /// NOTE: this is a pure function without side effects. It does not modify any state - /// directly, that is the responsibility of the caller. + /// NOTE: does not modify any storage, that is the responsibility of the caller. pub fn update_pool_rewards( mut pool_info: PoolInfoFor, ) -> Result, DispatchError> { diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index 25064d5a72e9..431e71b84f71 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -23,18 +23,15 @@ use core::default::Default; use frame_support::{ construct_runtime, derive_impl, instances::Instance1, - ord_parameter_types, parameter_types, + parameter_types, traits::{ tokens::fungible::{NativeFromLeft, NativeOrWithId, UnionOf}, AsEnsureOriginWithArg, ConstU128, ConstU32, EnsureOrigin, }, PalletId, }; -use frame_system::{ensure_signed, EnsureSigned}; -use sp_runtime::{ - traits::{AccountIdConversion, IdentityLookup}, - BuildStorage, -}; +use frame_system::EnsureSigned; +use sp_runtime::{traits::IdentityLookup, BuildStorage}; type Block = frame_system::mocking::MockBlock; @@ -99,24 +96,19 @@ impl pallet_assets::Config for MockRuntime { parameter_types! { pub const StakingRewardsPalletId: PalletId = PalletId(*b"py/stkrd"); pub const Native: NativeOrWithId = NativeOrWithId::Native; - pub const PermissionedAccountId: u128 = 1; -} -ord_parameter_types! { - pub const AssetConversionOrigin: u128 = AccountIdConversion::::into_account_truncating(&StakingRewardsPalletId::get()); + pub const PermissionedAccountId: u128 = 0; } -// Set account id 1 to the permissioned creator -pub struct MockPermissionedPoolCreator; -impl EnsureOrigin for MockPermissionedPoolCreator { - type Success = (); +/// Give Root Origin permission to create pools. +pub struct MockPermissionedOrigin; +impl EnsureOrigin for MockPermissionedOrigin { + type Success = ::AccountId; fn try_origin(origin: RuntimeOrigin) -> Result { - // Set account 1 to admin in tests - if ensure_signed(origin.clone()).map_or(false, |acc| acc == 1) { - return Ok(()); + match origin.clone().into() { + Ok(frame_system::RawOrigin::Root) => Ok(PermissionedAccountId::get()), + _ => Err(origin), } - - return Err(origin); } #[cfg(feature = "runtime-benchmarks")] @@ -133,7 +125,7 @@ impl Config for MockRuntime { type Balance = ::Balance; type Assets = NativeAndAssets; type PalletId = StakingRewardsPalletId; - type PermissionedPoolCreator = MockPermissionedPoolCreator; + type PermissionedOrigin = MockPermissionedOrigin; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); } @@ -144,10 +136,14 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities { pallet_assets::GenesisConfig:: { // Genesis assets: id, owner, is_sufficient, min_balance // pub assets: Vec<(T::AssetId, T::AccountId, bool, T::Balance)>, - assets: vec![(1, 1, true, 10000)], + assets: vec![(1, 1, true, 10000), (10, 1, true, 10000), (20, 1, true, 10000)], // Genesis metadata: id, name, symbol, decimals // pub metadata: Vec<(T::AssetId, Vec, Vec, u8)>, - metadata: vec![(1, b"test".to_vec(), b"TST".to_vec(), 18)], + metadata: vec![ + (1, b"test".to_vec(), b"TST".to_vec(), 18), + (10, b"test10".to_vec(), b"T10".to_vec(), 18), + (20, b"test20".to_vec(), b"T20".to_vec(), 18), + ], // Genesis accounts: id, account_id, balance // pub accounts: Vec<(T::AssetId, T::AccountId, T::Balance)>, accounts: vec![ diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 99b954ddbaf9..efa4c9676f45 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -19,6 +19,12 @@ use crate::{mock::*, *}; use frame_support::{assert_err, assert_ok, hypothetically, traits::fungible::NativeOrWithId}; use sp_runtime::{traits::BadOrigin, ArithmeticError, TokenError}; +const DEFAULT_STAKED_ASSET_ID: NativeOrWithId = NativeOrWithId::::WithId(1); +const DEFAULT_REWARD_ASSET_ID: NativeOrWithId = NativeOrWithId::::Native; +const DEFAULT_REWARD_RATE_PER_BLOCK: u128 = 100; +const DEFAULT_EXPIRY_BLOCK: u64 = 200; +const DEFAULT_ADMIN: u128 = 1; + /// Creates a basic pool with values: /// - Staking asset: 1 /// - Reward asset: Native @@ -29,13 +35,24 @@ use sp_runtime::{traits::BadOrigin, ArithmeticError, TokenError}; /// Useful to reduce boilerplate in tests when it's not important to customise or reusing pool /// params. pub fn create_default_pool() { - let staked_asset_id = NativeOrWithId::::WithId(1); assert_ok!(StakingRewards::create_pool( - RuntimeOrigin::signed(1), - Box::new(staked_asset_id), - Box::new(NativeOrWithId::::Native), - 100, - 100u64, + RuntimeOrigin::root(), + Box::new(DEFAULT_STAKED_ASSET_ID.clone()), + Box::new(DEFAULT_REWARD_ASSET_ID.clone()), + DEFAULT_REWARD_RATE_PER_BLOCK, + DEFAULT_EXPIRY_BLOCK, + Some(DEFAULT_ADMIN) + )); +} + +/// The same as [`create_default_pool`], but with the admin parameter set to `None`. +pub fn create_default_pool_permissioned_admin() { + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::root(), + Box::new(DEFAULT_STAKED_ASSET_ID.clone()), + Box::new(DEFAULT_REWARD_ASSET_ID.clone()), + DEFAULT_REWARD_RATE_PER_BLOCK, + DEFAULT_EXPIRY_BLOCK, None )); } @@ -92,19 +109,16 @@ mod create_pool { #[test] fn success() { new_test_ext().execute_with(|| { - let user = 1; - let staked_asset_id = NativeOrWithId::::Native; - let reward_asset_id = NativeOrWithId::::WithId(1); - let reward_rate_per_block = 100; - let expiry_block = 200u64; - assert_eq!(NextPoolId::::get(), 0); + + // Create a pool with default values, and no admin override so [`PermissionedAccountId`] + // is admin. assert_ok!(StakingRewards::create_pool( - RuntimeOrigin::signed(user), - Box::new(staked_asset_id.clone()), - Box::new(reward_asset_id.clone()), - reward_rate_per_block, - expiry_block, + RuntimeOrigin::root(), + Box::new(DEFAULT_STAKED_ASSET_ID), + Box::new(DEFAULT_REWARD_ASSET_ID), + DEFAULT_REWARD_RATE_PER_BLOCK, + DEFAULT_EXPIRY_BLOCK, None )); @@ -112,13 +126,13 @@ mod create_pool { assert_eq!( events(), [Event::::PoolCreated { - creator: user, + creator: PermissionedAccountId::get(), pool_id: 0, - staked_asset_id: staked_asset_id.clone(), - reward_asset_id: reward_asset_id.clone(), - reward_rate_per_block, - expiry_block, - admin: user, + staked_asset_id: DEFAULT_STAKED_ASSET_ID, + reward_asset_id: DEFAULT_REWARD_ASSET_ID, + reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, + expiry_block: DEFAULT_EXPIRY_BLOCK, + admin: PermissionedAccountId::get(), }] ); @@ -129,11 +143,11 @@ mod create_pool { vec![( 0, PoolInfo { - staked_asset_id: staked_asset_id.clone(), - reward_asset_id: reward_asset_id.clone(), - reward_rate_per_block, - expiry_block, - admin: user, + staked_asset_id: DEFAULT_STAKED_ASSET_ID, + reward_asset_id: DEFAULT_REWARD_ASSET_ID, + reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, + expiry_block: DEFAULT_EXPIRY_BLOCK, + admin: PermissionedAccountId::get(), total_tokens_staked: 0, reward_per_token_stored: 0, last_update_block: 0 @@ -141,10 +155,14 @@ mod create_pool { )] ); - // Create another pool with explicit admin. + // Create another pool with explicit admin and other overrides. let admin = 2; + let staked_asset_id = NativeOrWithId::::WithId(10); + let reward_asset_id = NativeOrWithId::::WithId(20); + let reward_rate_per_block = 250; + let expiry_block = 500; assert_ok!(StakingRewards::create_pool( - RuntimeOrigin::signed(user), + RuntimeOrigin::root(), Box::new(staked_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, @@ -156,7 +174,7 @@ mod create_pool { assert_eq!( events(), [Event::::PoolCreated { - creator: user, + creator: PermissionedAccountId::get(), pool_id: 1, staked_asset_id: staked_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), @@ -174,11 +192,11 @@ mod create_pool { ( 0, PoolInfo { - staked_asset_id: staked_asset_id.clone(), - reward_asset_id: reward_asset_id.clone(), - reward_rate_per_block, - admin: user, - expiry_block, + staked_asset_id: DEFAULT_STAKED_ASSET_ID, + reward_asset_id: DEFAULT_REWARD_ASSET_ID, + reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, + admin: PermissionedAccountId::get(), + expiry_block: DEFAULT_EXPIRY_BLOCK, total_tokens_staked: 0, reward_per_token_stored: 0, last_update_block: 0 @@ -210,7 +228,7 @@ mod create_pool { assert_err!( StakingRewards::create_pool( - RuntimeOrigin::signed(1), + RuntimeOrigin::root(), Box::new(valid_asset.clone()), Box::new(invalid_asset.clone()), 10, @@ -222,7 +240,7 @@ mod create_pool { assert_err!( StakingRewards::create_pool( - RuntimeOrigin::signed(1), + RuntimeOrigin::root(), Box::new(invalid_asset.clone()), Box::new(valid_asset.clone()), 10, @@ -234,7 +252,7 @@ mod create_pool { assert_err!( StakingRewards::create_pool( - RuntimeOrigin::signed(1), + RuntimeOrigin::root(), Box::new(invalid_asset.clone()), Box::new(invalid_asset.clone()), 10, @@ -247,7 +265,7 @@ mod create_pool { } #[test] - fn fails_for_not_admin() { + fn fails_for_not_permissioned() { new_test_ext().execute_with(|| { let user = 100; let staked_asset_id = NativeOrWithId::::Native; @@ -261,7 +279,7 @@ mod create_pool { Box::new(reward_asset_id.clone()), reward_rate_per_block, expiry_block, - Some(999) + None ), BadOrigin ); @@ -271,18 +289,14 @@ mod create_pool { #[test] fn fails_for_bad_expiry_block() { new_test_ext().execute_with(|| { - let user = 1; - let staked_asset_id = NativeOrWithId::::Native; - let reward_asset_id = NativeOrWithId::::WithId(1); - let reward_rate_per_block = 100; let expiry_block = 100u64; System::set_block_number(expiry_block + 1u64); assert_err!( StakingRewards::create_pool( - RuntimeOrigin::signed(user), - Box::new(staked_asset_id.clone()), - Box::new(reward_asset_id.clone()), - reward_rate_per_block, + RuntimeOrigin::root(), + Box::new(DEFAULT_STAKED_ASSET_ID), + Box::new(DEFAULT_REWARD_ASSET_ID), + DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block, None ), @@ -555,7 +569,7 @@ mod set_pool_admin { use super::*; #[test] - fn success() { + fn success_signed_admin() { new_test_ext().execute_with(|| { let admin = 1; let new_admin = 2; @@ -578,6 +592,25 @@ mod set_pool_admin { }); } + #[test] + fn success_permissioned_admin() { + new_test_ext().execute_with(|| { + let new_admin = 2; + let pool_id = 0; + create_default_pool_permissioned_admin(); + + // Modify the pool admin + assert_ok!(StakingRewards::set_pool_admin(RuntimeOrigin::root(), pool_id, new_admin)); + + // Check state + assert_eq!( + *events().last().unwrap(), + Event::::PoolAdminModified { pool_id, new_admin } + ); + assert_eq!(Pools::::get(pool_id).unwrap().admin, new_admin); + }); + } + #[test] fn fails_for_non_existent_pool() { new_test_ext().execute_with(|| { @@ -620,7 +653,29 @@ mod set_pool_expiry_block { use super::*; #[test] - fn updates_state_correctly() { + fn success_permissioned_admin() { + new_test_ext().execute_with(|| { + let pool_id = 0; + let new_expiry_block = 200u64; + create_default_pool_permissioned_admin(); + + assert_ok!(StakingRewards::set_pool_expiry_block( + RuntimeOrigin::root(), + pool_id, + new_expiry_block + )); + + // Check state + assert_eq!(Pools::::get(pool_id).unwrap().expiry_block, new_expiry_block); + assert_eq!( + *events().last().unwrap(), + Event::::PoolExpiryBlockModified { pool_id, new_expiry_block } + ); + }); + } + + #[test] + fn success_signed_admin() { new_test_ext().execute_with(|| { let admin = 1; let pool_id = 0; @@ -648,18 +703,28 @@ mod set_pool_expiry_block { let admin = 1; let staker = 2; let pool_id = 0; - let new_expiry_block = 200u64; + let new_expiry_block = 300u64; create_default_pool(); // Regular reward accumulation System::set_block_number(10); assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker), pool_id, 1000)); System::set_block_number(20); - assert_hypothetically_earned(staker, 100 * 10, pool_id, NativeOrWithId::::Native); + assert_hypothetically_earned( + staker, + DEFAULT_REWARD_RATE_PER_BLOCK * 10, + pool_id, + NativeOrWithId::::Native, + ); - // Expiry was block 100, or only earned 90 blocks at block 150 - System::set_block_number(150); - assert_hypothetically_earned(staker, 100 * 90, pool_id, NativeOrWithId::::Native); + // Expiry was block 200, so earned 190 at block 250 + System::set_block_number(250); + assert_hypothetically_earned( + staker, + DEFAULT_REWARD_RATE_PER_BLOCK * 190, + pool_id, + NativeOrWithId::::Native, + ); // Extend expiry 50 more blocks assert_ok!(StakingRewards::set_pool_expiry_block( @@ -667,10 +732,15 @@ mod set_pool_expiry_block { pool_id, new_expiry_block )); - System::set_block_number(300); + System::set_block_number(350); - // Staker has been in pool with rewards active for 140 blocks total - assert_hypothetically_earned(staker, 100 * 140, pool_id, NativeOrWithId::::Native); + // Staker has been in pool with rewards active for 240 blocks total + assert_hypothetically_earned( + staker, + DEFAULT_REWARD_RATE_PER_BLOCK * 240, + pool_id, + NativeOrWithId::::Native, + ); }); } @@ -763,15 +833,46 @@ mod set_pool_reward_rate_per_block { use super::*; #[test] - fn state_is_modified_correctly() { + fn success_signed_admin() { new_test_ext().execute_with(|| { - let admin = 1; let pool_id = 0; let new_reward_rate = 200; create_default_pool(); + // Pool Admin can modify assert_ok!(StakingRewards::set_pool_reward_rate_per_block( - RuntimeOrigin::signed(admin), + RuntimeOrigin::signed(DEFAULT_ADMIN), + pool_id, + new_reward_rate + )); + + // Check state + assert_eq!( + Pools::::get(pool_id).unwrap().reward_rate_per_block, + new_reward_rate + ); + + // Check event + assert_eq!( + *events().last().unwrap(), + Event::::PoolRewardRateModified { + pool_id, + new_reward_rate_per_block: new_reward_rate + } + ); + }); + } + + #[test] + fn success_permissioned_admin() { + new_test_ext().execute_with(|| { + let pool_id = 0; + let new_reward_rate = 200; + create_default_pool_permissioned_admin(); + + // Root can modify + assert_ok!(StakingRewards::set_pool_reward_rate_per_block( + RuntimeOrigin::root(), pool_id, new_reward_rate )); @@ -925,13 +1026,58 @@ mod withdraw_reward_tokens { use super::*; #[test] - fn success() { + fn success_permissioned_admin() { new_test_ext().execute_with(|| { let admin = 1; let pool_id = 0; let reward_asset_id = NativeOrWithId::::Native; let initial_deposit = 10; let withdraw_amount = 5; + let dest = 10u128; + create_default_pool_permissioned_admin(); + let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); + + // Deposit initial reward tokens + assert_ok!(StakingRewards::deposit_reward_tokens( + RuntimeOrigin::signed(admin), + pool_id, + initial_deposit + )); + + // Withdraw some tokens + let dest_balance_before = + <::Assets>::balance(reward_asset_id.clone(), &dest); + let pool_balance_before = <::Assets>::balance( + reward_asset_id.clone(), + &pool_account_id, + ); + assert_ok!(StakingRewards::withdraw_reward_tokens( + RuntimeOrigin::root(), + pool_id, + withdraw_amount, + dest + )); + let dest_balance_after = + <::Assets>::balance(reward_asset_id.clone(), &dest); + let pool_balance_after = <::Assets>::balance( + reward_asset_id.clone(), + &pool_account_id, + ); + + assert_eq!(pool_balance_after, pool_balance_before - withdraw_amount); + assert_eq!(dest_balance_after, dest_balance_before + withdraw_amount); + }); + } + + #[test] + fn success_signed_origin() { + new_test_ext().execute_with(|| { + let admin = 1; + let pool_id = 0; + let reward_asset_id = NativeOrWithId::::Native; + let initial_deposit = 10; + let withdraw_amount = 5; + let dest = 10u128; create_default_pool(); let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); @@ -943,8 +1089,8 @@ mod withdraw_reward_tokens { )); // Withdraw some tokens - let admin_balance_before = - <::Assets>::balance(reward_asset_id.clone(), &admin); + let dest_balance_before = + <::Assets>::balance(reward_asset_id.clone(), &dest); let pool_balance_before = <::Assets>::balance( reward_asset_id.clone(), &pool_account_id, @@ -952,17 +1098,18 @@ mod withdraw_reward_tokens { assert_ok!(StakingRewards::withdraw_reward_tokens( RuntimeOrigin::signed(admin), pool_id, - withdraw_amount + withdraw_amount, + dest )); - let admin_balance_after = - <::Assets>::balance(reward_asset_id.clone(), &admin); + let dest_balance_after = + <::Assets>::balance(reward_asset_id.clone(), &dest); let pool_balance_after = <::Assets>::balance( reward_asset_id.clone(), &pool_account_id, ); assert_eq!(pool_balance_after, pool_balance_before - withdraw_amount); - assert_eq!(admin_balance_after, admin_balance_before + withdraw_amount); + assert_eq!(dest_balance_after, dest_balance_before + withdraw_amount); }); } @@ -970,7 +1117,7 @@ mod withdraw_reward_tokens { fn fails_for_non_existent_pool() { new_test_ext().execute_with(|| { assert_err!( - StakingRewards::withdraw_reward_tokens(RuntimeOrigin::signed(1), 900, 100), + StakingRewards::withdraw_reward_tokens(RuntimeOrigin::signed(1), 900, 100, 1u128), Error::::NonExistentPool ); }); @@ -981,7 +1128,7 @@ mod withdraw_reward_tokens { new_test_ext().execute_with(|| { create_default_pool(); assert_err!( - StakingRewards::withdraw_reward_tokens(RuntimeOrigin::signed(5), 0, 100), + StakingRewards::withdraw_reward_tokens(RuntimeOrigin::signed(5), 0, 100, 1u128), BadOrigin ); }); @@ -1009,7 +1156,8 @@ mod withdraw_reward_tokens { StakingRewards::withdraw_reward_tokens( RuntimeOrigin::signed(admin), pool_id, - withdraw_amount + withdraw_amount, + admin ), TokenError::FundsUnavailable ); @@ -1037,12 +1185,12 @@ fn integration() { let reward_rate_per_block = 100; let expiry_block = 25u64.into(); assert_ok!(StakingRewards::create_pool( - RuntimeOrigin::signed(admin), + RuntimeOrigin::root(), Box::new(staked_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, expiry_block, - None + Some(admin) )); let pool_id = 0; @@ -1168,7 +1316,7 @@ fn integration() { events(), [ Event::PoolCreated { - creator: admin, + creator: PermissionedAccountId::get(), pool_id, staked_asset_id, reward_asset_id, From 8d0476b0b1edae2c8e67d52d1ac641a08471ee66 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 10 Apr 2024 16:14:39 +0400 Subject: [PATCH 049/159] update pallet benchmarks --- .../frame/asset-rewards/src/benchmarking.rs | 134 +++++++++++------- substrate/frame/asset-rewards/src/mock.rs | 2 +- 2 files changed, 83 insertions(+), 53 deletions(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 3b50e718d34d..290306aa24b7 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -25,6 +25,7 @@ use frame_support::{ traits::{ fungible::NativeOrWithId, fungibles::{Create, Inspect, Mutate}, + EnsureOrigin, }, }; use frame_system::RawOrigin; @@ -37,8 +38,6 @@ pub trait BenchmarkHelper { fn to_asset_id(seed: NativeOrWithId) -> AssetId; /// Convert a u32 to an AccountId fn to_account_id(seed: u32) -> AccountId; - /// Get the permissioned pool creator - fn permissioned_pool_creator() -> AccountId; } impl BenchmarkHelper for () @@ -52,9 +51,6 @@ where fn to_account_id(seed: u32) -> AccountId { seed.into() } - fn permissioned_pool_creator() -> AccountId { - 1u32.into() - } } /// Create the `asset` and mint the `amount` for the `caller`. @@ -88,15 +84,16 @@ mod benchmarks { fn create_pool() { use super::*; - let admin = T::BenchmarkHelper::permissioned_pool_creator(); + let origin = T::PermissionedOrigin::try_successful_origin().unwrap(); + let acc = T::PermissionedOrigin::ensure_origin(origin.clone()).unwrap(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + create_asset::(&acc, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); + create_asset::(&acc, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); #[extrinsic_call] _( - RawOrigin::Signed(admin.clone()), + origin as T::RuntimeOrigin, Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -106,8 +103,8 @@ mod benchmarks { assert_last_event::( Event::PoolCreated { - creator: admin.clone(), - admin, + creator: acc.clone(), + admin: acc, staked_asset_id: staked_asset, reward_asset_id: reward_asset, reward_rate_per_block: 100u32.into(), @@ -122,15 +119,15 @@ mod benchmarks { fn stake() { use super::*; - let admin = T::BenchmarkHelper::permissioned_pool_creator(); + let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); let staker = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&staker, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + create_asset::(&staker, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); assert_ok!(AssetRewards::::create_pool( - RawOrigin::Signed(admin.clone()).into(), + permissioned as T::RuntimeOrigin, Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -150,15 +147,15 @@ mod benchmarks { fn unstake() { use super::*; - let admin = T::BenchmarkHelper::permissioned_pool_creator(); + let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); let staker = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&staker, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + create_asset::(&staker, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); assert_ok!(AssetRewards::::create_pool( - RawOrigin::Signed(admin.clone()).into(), + permissioned as T::RuntimeOrigin, Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -184,15 +181,15 @@ mod benchmarks { fn harvest_rewards() { use super::*; - let admin = T::BenchmarkHelper::permissioned_pool_creator(); + let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); let staker = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_asset::(&staker, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + create_asset::(&staker, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); assert_ok!(AssetRewards::::create_pool( - RawOrigin::Signed(admin.clone()).into(), + permissioned, Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -224,14 +221,15 @@ mod benchmarks { fn set_pool_reward_rate_per_block() { use super::*; - let admin = T::BenchmarkHelper::permissioned_pool_creator(); + let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); + let acc = T::BenchmarkHelper::to_account_id(1); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + create_asset::(&acc, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); + create_asset::(&acc, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); assert_ok!(AssetRewards::::create_pool( - RawOrigin::Signed(admin.clone()).into(), + permissioned.clone() as T::RuntimeOrigin, Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -240,7 +238,7 @@ mod benchmarks { )); #[extrinsic_call] - _(RawOrigin::Signed(admin.clone()), 0u32.into(), 5u32.into()); + _(permissioned as T::RuntimeOrigin, 0u32.into(), 5u32.into()); assert_last_event::( Event::PoolRewardRateModified { @@ -255,15 +253,23 @@ mod benchmarks { fn set_pool_admin() { use super::*; - let admin = T::BenchmarkHelper::permissioned_pool_creator(); + let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); let new_admin = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + create_asset::( + &new_admin, + &staked_asset, + T::Assets::minimum_balance(staked_asset.clone()), + ); + create_asset::( + &new_admin, + &reward_asset, + T::Assets::minimum_balance(reward_asset.clone()), + ); assert_ok!(AssetRewards::::create_pool( - RawOrigin::Signed(admin.clone()).into(), + permissioned.clone() as T::RuntimeOrigin, Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -272,7 +278,7 @@ mod benchmarks { )); #[extrinsic_call] - _(RawOrigin::Signed(admin.clone()), 0u32.into(), new_admin.clone()); + _(permissioned as T::RuntimeOrigin, 0u32.into(), new_admin.clone()); assert_last_event::(Event::PoolAdminModified { pool_id: 0u32.into(), new_admin }.into()); } @@ -281,14 +287,15 @@ mod benchmarks { fn set_pool_expiry_block() { use super::*; - let admin = T::BenchmarkHelper::permissioned_pool_creator(); + let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + let acc = T::BenchmarkHelper::to_account_id(1); + create_asset::(&acc, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); + create_asset::(&acc, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); assert_ok!(AssetRewards::::create_pool( - RawOrigin::Signed(admin.clone()).into(), + permissioned.clone() as T::RuntimeOrigin, Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -297,7 +304,7 @@ mod benchmarks { )); #[extrinsic_call] - _(RawOrigin::Signed(admin.clone()), 0u32.into(), 1000u32.into()); + _(permissioned as T::RuntimeOrigin, 0u32.into(), 1000u32.into()); assert_last_event::( Event::PoolExpiryBlockModified { @@ -312,15 +319,24 @@ mod benchmarks { fn deposit_reward_tokens() { use super::*; - let admin = T::BenchmarkHelper::permissioned_pool_creator(); + let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); + let permissioned_acc = T::PermissionedOrigin::ensure_origin(permissioned.clone()).unwrap(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + create_asset::( + &permissioned_acc, + &staked_asset, + T::Assets::minimum_balance(staked_asset.clone()), + ); + create_asset::( + &permissioned_acc, + &reward_asset, + T::Assets::minimum_balance(reward_asset.clone()), + ); - T::Assets::set_balance(reward_asset.clone(), &admin, 100000u32.into()); + T::Assets::set_balance(reward_asset.clone(), &permissioned_acc, 100000u32.into()); assert_ok!(AssetRewards::::create_pool( - RawOrigin::Signed(admin.clone()).into(), + permissioned.clone() as T::RuntimeOrigin, Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -328,12 +344,12 @@ mod benchmarks { None, )); - let balance_before = T::Assets::balance(reward_asset.clone(), &admin); + let balance_before = T::Assets::balance(reward_asset.clone(), &permissioned_acc); #[extrinsic_call] - _(RawOrigin::Signed(admin.clone()), 0u32.into(), 10u32.into()); + _(RawOrigin::Signed(permissioned_acc.clone()), 0u32.into(), 10u32.into()); - let balance_after = T::Assets::balance(reward_asset.clone(), &admin); + let balance_after = T::Assets::balance(reward_asset.clone(), &permissioned_acc); assert_eq!(balance_after, balance_before - 10u32.into()); } @@ -342,15 +358,24 @@ mod benchmarks { fn withdraw_reward_tokens() { use super::*; - let admin = T::BenchmarkHelper::permissioned_pool_creator(); + let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); + let permissioned_acc = T::PermissionedOrigin::ensure_origin(permissioned.clone()).unwrap(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::(&admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + create_asset::( + &permissioned_acc, + &staked_asset, + T::Assets::minimum_balance(staked_asset.clone()), + ); + create_asset::( + &permissioned_acc, + &reward_asset, + T::Assets::minimum_balance(reward_asset.clone()), + ); - T::Assets::set_balance(reward_asset.clone(), &admin, 100000u32.into()); + T::Assets::set_balance(reward_asset.clone(), &permissioned_acc, 100000u32.into()); assert_ok!(AssetRewards::::create_pool( - RawOrigin::Signed(admin.clone()).into(), + permissioned.clone() as T::RuntimeOrigin, Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -358,18 +383,23 @@ mod benchmarks { None, )); - let balance_before = T::Assets::balance(reward_asset.clone(), &admin); + let balance_before = T::Assets::balance(reward_asset.clone(), &permissioned_acc); assert_ok!(AssetRewards::::deposit_reward_tokens( - RawOrigin::Signed(admin.clone()).into(), + RawOrigin::Signed(permissioned_acc.clone()).into(), 0u32.into(), 10u32.into() )); #[extrinsic_call] - _(RawOrigin::Signed(admin.clone()), 0u32.into(), 5u32.into()); + _( + RawOrigin::Signed(permissioned_acc.clone()), + 0u32.into(), + 5u32.into(), + permissioned_acc.clone(), + ); - let balance_after = T::Assets::balance(reward_asset.clone(), &admin); + let balance_after = T::Assets::balance(reward_asset.clone(), &permissioned_acc); // Deposited 10, withdrew 5 assert_eq!(balance_after, balance_before - 5u32.into()); diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index 431e71b84f71..dad428c4d44a 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -113,7 +113,7 @@ impl EnsureOrigin for MockPermissionedOrigin { #[cfg(feature = "runtime-benchmarks")] fn try_successful_origin() -> Result { - todo!() + Ok(RuntimeOrigin::root()) } } From 9389c4790ff8dee2f78c7495842dd65b96c498e4 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Thu, 11 Apr 2024 12:13:09 +0400 Subject: [PATCH 050/159] benchmarks finally working for node-template --- substrate/bin/node/runtime/src/lib.rs | 32 +++- .../frame/asset-rewards/src/benchmarking.rs | 157 +++++++++++++----- 2 files changed, 135 insertions(+), 54 deletions(-) diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index c6000710c5c7..3757059c1d8f 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -45,9 +45,9 @@ use frame_support::{ GetSalary, PayFromAccount, }, AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU16, ConstU32, Contains, Currency, - EitherOfDiverse, EnsureOriginWithArg, EqualPrivilegeOnly, Imbalance, InsideBoth, - InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, LockIdentifier, Nothing, - OnUnbalanced, WithdrawReasons, + EitherOfDiverse, EnsureOrigin, EnsureOriginWithArg, EqualPrivilegeOnly, Imbalance, + InsideBoth, InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, LockIdentifier, + Nothing, OnUnbalanced, WithdrawReasons, }, weights::{ constants::{ @@ -71,13 +71,11 @@ use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use pallet_nfts::PalletFeatures; use pallet_nis::WithMaximumOf; use pallet_session::historical as pallet_session_historical; -use sp_core::TypedGet; // Can't use `FungibleAdapter` here until Treasury pallet migrates to fungibles // #[allow(deprecated)] pub use pallet_transaction_payment::{CurrencyAdapter, Multiplier, TargetedFeeAdjustment}; use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; -use pallet_treasury::TreasuryAccountId; use pallet_tx_pause::RuntimeCallNameOf; use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; @@ -1752,8 +1750,26 @@ impl pallet_asset_rewards::benchmarking::BenchmarkHelper, Ac bytes[0..4].copy_from_slice(&seed.to_be_bytes()); // Place the u32 value at the beginning (big-endian for this example) bytes.into() } - fn permissioned_pool_creator() -> AccountId { - TreasuryAccountId::::get() + fn sufficient_asset() -> NativeOrWithId { + NativeOrWithId::::Native + } +} + +/// Give Root Origin permission to create pools, and an acc id of 0. +pub struct AssetRewardsPermissionedOrigin; +impl EnsureOrigin for AssetRewardsPermissionedOrigin { + type Success = ::AccountId; + + fn try_origin(origin: RuntimeOrigin) -> Result { + match origin.clone().into() { + Ok(frame_system::RawOrigin::Root) => Ok([0u8; 32].into()), + _ => Err(origin), + } + } + + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin() -> Result { + Ok(RuntimeOrigin::root()) } } @@ -1763,7 +1779,7 @@ impl pallet_asset_rewards::Config for Runtime { type Balance = u128; type Assets = NativeAndAssets; type PalletId = StakingRewardsPalletId; - type PermissionedOrigin = EnsureRoot; + type PermissionedOrigin = AssetRewardsPermissionedOrigin; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = AssetRewardsBenchmarkHelper; } diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 290306aa24b7..847385dd412f 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -29,7 +29,7 @@ use frame_support::{ }, }; use frame_system::RawOrigin; -use sp_runtime::traits::One; +use sp_runtime::{traits::One, SaturatedConversion}; use sp_std::prelude::*; /// Benchmark Helper @@ -38,6 +38,8 @@ pub trait BenchmarkHelper { fn to_asset_id(seed: NativeOrWithId) -> AssetId; /// Convert a u32 to an AccountId fn to_account_id(seed: u32) -> AccountId; + /// Return the ID of the asset whos minimum balance is sufficient for an account to exist + fn sufficient_asset() -> AssetId; } impl BenchmarkHelper for () @@ -51,10 +53,26 @@ where fn to_account_id(seed: u32) -> AccountId { seed.into() } + fn sufficient_asset() -> AssetId { + NativeOrWithId::Native.into() + } +} + +/// Create and mint the minimum amount of the sufficient asset. +fn create_and_mint_sufficient(caller: &T::AccountId) +where + T::Assets: Create + Mutate, +{ + let sufficient_asset = T::BenchmarkHelper::sufficient_asset(); + create_and_mint_asset::( + &caller, + &sufficient_asset.clone(), + T::Assets::minimum_balance(sufficient_asset), + ); } /// Create the `asset` and mint the `amount` for the `caller`. -fn create_asset(caller: &T::AccountId, asset: &T::AssetId, amount: T::Balance) +fn create_and_mint_asset(caller: &T::AccountId, asset: &T::AssetId, amount: T::Balance) where T::Assets: Create + Mutate, { @@ -88,8 +106,16 @@ mod benchmarks { let acc = T::PermissionedOrigin::ensure_origin(origin.clone()).unwrap(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::(&acc, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&acc, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + create_and_mint_asset::( + &acc, + &staked_asset, + T::Assets::minimum_balance(staked_asset.clone()), + ); + create_and_mint_asset::( + &acc, + &reward_asset, + T::Assets::minimum_balance(reward_asset.clone()), + ); #[extrinsic_call] _( @@ -123,8 +149,16 @@ mod benchmarks { let staker = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::(&staker, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&staker, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + create_and_mint_asset::( + &staker, + &staked_asset, + T::Assets::minimum_balance(staked_asset.clone()), + ); + create_and_mint_asset::( + &staker, + &reward_asset, + T::Assets::minimum_balance(reward_asset.clone()), + ); assert_ok!(AssetRewards::::create_pool( permissioned as T::RuntimeOrigin, @@ -151,8 +185,16 @@ mod benchmarks { let staker = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::(&staker, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&staker, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + create_and_mint_asset::( + &staker, + &staked_asset, + T::Assets::minimum_balance(staked_asset.clone()), + ); + create_and_mint_asset::( + &staker, + &reward_asset, + T::Assets::minimum_balance(reward_asset.clone()), + ); assert_ok!(AssetRewards::::create_pool( permissioned as T::RuntimeOrigin, @@ -181,13 +223,22 @@ mod benchmarks { fn harvest_rewards() { use super::*; + let block_number_before = frame_system::Pallet::::block_number(); + let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); let staker = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::(&staker, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&staker, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); - + create_and_mint_asset::( + &staker, + &staked_asset, + T::Assets::minimum_balance(staked_asset.clone()), + ); + create_and_mint_asset::( + &staker, + &reward_asset, + T::Assets::minimum_balance(reward_asset.clone()), + ); assert_ok!(AssetRewards::::create_pool( permissioned, Box::new(staked_asset.clone()), @@ -197,6 +248,9 @@ mod benchmarks { None, )); + let pool_acc = AssetRewards::::pool_account_id(&0u32).unwrap(); + create_and_mint_sufficient::(&pool_acc); + create_and_mint_asset::(&pool_acc, &reward_asset, 100_000u32.into()); assert_ok!(AssetRewards::::stake( RawOrigin::Signed(staker.clone()).into(), 0u32.into(), @@ -206,12 +260,20 @@ mod benchmarks { #[extrinsic_call] _(RawOrigin::Signed(staker.clone()), 0u32.into(), None); + let block_number_after = frame_system::Pallet::::block_number(); + + // In tests a block doesn't pass but when running benchmarks for node-template one does. + // Not sure why, but adding this to correctly calculate the harvested amount. + // + // TODO: Before merging understand this + let blocks_elapsed = block_number_after - block_number_before; + assert_last_event::( Event::RewardsHarvested { who: staker.clone(), staker, pool_id: 0u32.into(), - amount: 0u32.into(), + amount: (blocks_elapsed * 100u8.into()).saturated_into::().into(), } .into(), ); @@ -225,8 +287,16 @@ mod benchmarks { let acc = T::BenchmarkHelper::to_account_id(1); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::(&acc, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&acc, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + create_and_mint_asset::( + &acc, + &staked_asset, + T::Assets::minimum_balance(staked_asset.clone()), + ); + create_and_mint_asset::( + &acc, + &reward_asset, + T::Assets::minimum_balance(reward_asset.clone()), + ); assert_ok!(AssetRewards::::create_pool( permissioned.clone() as T::RuntimeOrigin, @@ -257,12 +327,12 @@ mod benchmarks { let new_admin = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::( + create_and_mint_asset::( &new_admin, &staked_asset, T::Assets::minimum_balance(staked_asset.clone()), ); - create_asset::( + create_and_mint_asset::( &new_admin, &reward_asset, T::Assets::minimum_balance(reward_asset.clone()), @@ -291,8 +361,16 @@ mod benchmarks { let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); let acc = T::BenchmarkHelper::to_account_id(1); - create_asset::(&acc, &staked_asset, T::Assets::minimum_balance(staked_asset.clone())); - create_asset::(&acc, &reward_asset, T::Assets::minimum_balance(reward_asset.clone())); + create_and_mint_asset::( + &acc, + &staked_asset, + T::Assets::minimum_balance(staked_asset.clone()), + ); + create_and_mint_asset::( + &acc, + &reward_asset, + T::Assets::minimum_balance(reward_asset.clone()), + ); assert_ok!(AssetRewards::::create_pool( permissioned.clone() as T::RuntimeOrigin, @@ -323,18 +401,9 @@ mod benchmarks { let permissioned_acc = T::PermissionedOrigin::ensure_origin(permissioned.clone()).unwrap(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::( - &permissioned_acc, - &staked_asset, - T::Assets::minimum_balance(staked_asset.clone()), - ); - create_asset::( - &permissioned_acc, - &reward_asset, - T::Assets::minimum_balance(reward_asset.clone()), - ); + create_and_mint_asset::(&permissioned_acc, &reward_asset, 100_000u32.into()); + create_and_mint_asset::(&permissioned_acc, &staked_asset, 100_000u32.into()); - T::Assets::set_balance(reward_asset.clone(), &permissioned_acc, 100000u32.into()); assert_ok!(AssetRewards::::create_pool( permissioned.clone() as T::RuntimeOrigin, Box::new(staked_asset.clone()), @@ -344,14 +413,17 @@ mod benchmarks { None, )); + let pool_acc = AssetRewards::::pool_account_id(&0u32).unwrap(); + create_and_mint_sufficient::(&pool_acc); + let balance_before = T::Assets::balance(reward_asset.clone(), &permissioned_acc); #[extrinsic_call] - _(RawOrigin::Signed(permissioned_acc.clone()), 0u32.into(), 10u32.into()); + _(RawOrigin::Signed(permissioned_acc.clone()), 0u32.into(), 10_000u32.into()); let balance_after = T::Assets::balance(reward_asset.clone(), &permissioned_acc); - assert_eq!(balance_after, balance_before - 10u32.into()); + assert_eq!(balance_after, balance_before - 10_000u32.into()); } #[benchmark] @@ -362,18 +434,9 @@ mod benchmarks { let permissioned_acc = T::PermissionedOrigin::ensure_origin(permissioned.clone()).unwrap(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_asset::( - &permissioned_acc, - &staked_asset, - T::Assets::minimum_balance(staked_asset.clone()), - ); - create_asset::( - &permissioned_acc, - &reward_asset, - T::Assets::minimum_balance(reward_asset.clone()), - ); + create_and_mint_asset::(&permissioned_acc, &staked_asset, 10000u32.into()); + create_and_mint_asset::(&permissioned_acc, &reward_asset, 10000u32.into()); - T::Assets::set_balance(reward_asset.clone(), &permissioned_acc, 100000u32.into()); assert_ok!(AssetRewards::::create_pool( permissioned.clone() as T::RuntimeOrigin, Box::new(staked_asset.clone()), @@ -382,27 +445,29 @@ mod benchmarks { 200u32.into(), None, )); + let pool_acc = AssetRewards::::pool_account_id(&0u32).unwrap(); + create_and_mint_sufficient::(&pool_acc); let balance_before = T::Assets::balance(reward_asset.clone(), &permissioned_acc); assert_ok!(AssetRewards::::deposit_reward_tokens( RawOrigin::Signed(permissioned_acc.clone()).into(), 0u32.into(), - 10u32.into() + 100u32.into() )); #[extrinsic_call] _( RawOrigin::Signed(permissioned_acc.clone()), 0u32.into(), - 5u32.into(), + 50u32.into(), permissioned_acc.clone(), ); let balance_after = T::Assets::balance(reward_asset.clone(), &permissioned_acc); - // Deposited 10, withdrew 5 - assert_eq!(balance_after, balance_before - 5u32.into()); + // Deposited 100, withdrew 50 + assert_eq!(balance_after, balance_before - 50u32.into()); } impl_benchmark_test_suite!(AssetRewards, crate::mock::new_test_ext(), crate::mock::MockRuntime); From c3ab0014d606bfc0d0182d4b07b89f5b155aa877 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Thu, 11 Apr 2024 08:55:11 +0000 Subject: [PATCH 051/159] ".git/.scripts/commands/bench-all/bench-all.sh" --pallet=pallet_asset_rewards --- substrate/frame/asset-rewards/src/weights.rs | 300 +++++++++++++++++++ 1 file changed, 300 insertions(+) diff --git a/substrate/frame/asset-rewards/src/weights.rs b/substrate/frame/asset-rewards/src/weights.rs index e69de29bb2d1..7deb3f6b77a1 100644 --- a/substrate/frame/asset-rewards/src/weights.rs +++ b/substrate/frame/asset-rewards/src/weights.rs @@ -0,0 +1,300 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Autogenerated weights for `pallet_asset_rewards` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-04-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// target/production/substrate-node +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_asset_rewards +// --chain=dev +// --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/asset-rewards/src/weights.rs +// --template=./substrate/.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `pallet_asset_rewards`. +pub trait WeightInfo { + fn create_pool() -> Weight; + fn stake() -> Weight; + fn unstake() -> Weight; + fn harvest_rewards() -> Weight; + fn set_pool_reward_rate_per_block() -> Weight; + fn set_pool_admin() -> Weight; + fn set_pool_expiry_block() -> Weight; + fn deposit_reward_tokens() -> Weight; + fn withdraw_reward_tokens() -> Weight; +} + +/// Weights for `pallet_asset_rewards` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::NextPoolId` (r:1 w:1) + /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::Pools` (r:0 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn create_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `333` + // Estimated: `3675` + // Minimum execution time: 15_461_000 picoseconds. + Weight::from_parts(16_048_000, 3675) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn stake() -> Weight { + // Proof Size summary in bytes: + // Measured: `277` + // Estimated: `3742` + // Minimum execution time: 17_959_000 picoseconds. + Weight::from_parts(18_708_000, 3742) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn unstake() -> Weight { + // Proof Size summary in bytes: + // Measured: `417` + // Estimated: `3882` + // Minimum execution time: 21_580_000 picoseconds. + Weight::from_parts(22_478_000, 3882) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:0) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn harvest_rewards() -> Weight { + // Proof Size summary in bytes: + // Measured: `660` + // Estimated: `6196` + // Minimum execution time: 58_827_000 picoseconds. + Weight::from_parts(59_910_000, 6196) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_pool_reward_rate_per_block() -> Weight { + // Proof Size summary in bytes: + // Measured: `277` + // Estimated: `3742` + // Minimum execution time: 13_068_000 picoseconds. + Weight::from_parts(13_753_000, 3742) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_pool_admin() -> Weight { + // Proof Size summary in bytes: + // Measured: `277` + // Estimated: `3742` + // Minimum execution time: 12_921_000 picoseconds. + Weight::from_parts(13_542_000, 3742) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_pool_expiry_block() -> Weight { + // Proof Size summary in bytes: + // Measured: `277` + // Estimated: `3742` + // Minimum execution time: 13_628_000 picoseconds. + Weight::from_parts(14_245_000, 3742) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:0) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn deposit_reward_tokens() -> Weight { + // Proof Size summary in bytes: + // Measured: `520` + // Estimated: `6196` + // Minimum execution time: 45_885_000 picoseconds. + Weight::from_parts(47_405_000, 6196) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:0) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn withdraw_reward_tokens() -> Weight { + // Proof Size summary in bytes: + // Measured: `520` + // Estimated: `6196` + // Minimum execution time: 45_973_000 picoseconds. + Weight::from_parts(47_179_000, 6196) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::NextPoolId` (r:1 w:1) + /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::Pools` (r:0 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn create_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `333` + // Estimated: `3675` + // Minimum execution time: 15_461_000 picoseconds. + Weight::from_parts(16_048_000, 3675) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn stake() -> Weight { + // Proof Size summary in bytes: + // Measured: `277` + // Estimated: `3742` + // Minimum execution time: 17_959_000 picoseconds. + Weight::from_parts(18_708_000, 3742) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn unstake() -> Weight { + // Proof Size summary in bytes: + // Measured: `417` + // Estimated: `3882` + // Minimum execution time: 21_580_000 picoseconds. + Weight::from_parts(22_478_000, 3882) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:0) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn harvest_rewards() -> Weight { + // Proof Size summary in bytes: + // Measured: `660` + // Estimated: `6196` + // Minimum execution time: 58_827_000 picoseconds. + Weight::from_parts(59_910_000, 6196) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_pool_reward_rate_per_block() -> Weight { + // Proof Size summary in bytes: + // Measured: `277` + // Estimated: `3742` + // Minimum execution time: 13_068_000 picoseconds. + Weight::from_parts(13_753_000, 3742) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_pool_admin() -> Weight { + // Proof Size summary in bytes: + // Measured: `277` + // Estimated: `3742` + // Minimum execution time: 12_921_000 picoseconds. + Weight::from_parts(13_542_000, 3742) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_pool_expiry_block() -> Weight { + // Proof Size summary in bytes: + // Measured: `277` + // Estimated: `3742` + // Minimum execution time: 13_628_000 picoseconds. + Weight::from_parts(14_245_000, 3742) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:0) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn deposit_reward_tokens() -> Weight { + // Proof Size summary in bytes: + // Measured: `520` + // Estimated: `6196` + // Minimum execution time: 45_885_000 picoseconds. + Weight::from_parts(47_405_000, 6196) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:0) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn withdraw_reward_tokens() -> Weight { + // Proof Size summary in bytes: + // Measured: `520` + // Estimated: `6196` + // Minimum execution time: 45_973_000 picoseconds. + Weight::from_parts(47_179_000, 6196) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } +} From 6c171370262e25aa110a7652afa1be5cdf722e79 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Thu, 11 Apr 2024 14:43:38 +0400 Subject: [PATCH 052/159] wip asset-hub-rococo benchmarks --- .../assets/asset-hub-rococo/Cargo.toml | 3 ++ .../assets/asset-hub-rococo/src/lib.rs | 45 ++++++++++++++++--- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml index c2090d102a56..035ca061af1f 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml @@ -144,6 +144,7 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", + "pallet-asset-rewards/runtime-benchmarks" ] try-runtime = [ "cumulus-pallet-aura-ext/try-runtime", @@ -177,6 +178,7 @@ try-runtime = [ "parachain-info/try-runtime", "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", + "pallet-asset-rewards/try-runtime" ] std = [ "assets-common/std", @@ -252,6 +254,7 @@ std = [ "xcm-builder/std", "xcm-executor/std", "xcm/std", + "pallet-asset-rewards/std" ] # A feature that should be enabled when the runtime should be built for on-chain diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 22687addb57c..9d75f8854f57 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -68,7 +68,7 @@ use frame_support::{ }; use frame_system::{ limits::{BlockLength, BlockWeights}, - EnsureRoot, EnsureSigned, EnsureSignedBy, + EnsureRoot, EnsureSigned, EnsureSignedBy, EnsureWithSuccess, }; use pallet_asset_conversion_tx_payment::AssetConversionAdapter; use pallet_nfts::PalletFeatures; @@ -77,6 +77,7 @@ use parachains_common::{ message_queue::{NarrowOriginToSibling, ParaIdToSibling}, AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, CollectionId, Hash, Header, ItemId, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, NORMAL_DISPATCH_RATIO, + TREASURY_PALLET_ID, }; use sp_runtime::{Perbill, RuntimeDebug}; use testnet_parachains_constants::rococo::{consensus::*, currency::*, fee::WeightToFee, time::*}; @@ -336,7 +337,7 @@ pub type NativeAndNonPoolAssets = fungible::UnionOf< /// Union fungibles implementation for [`PoolAssets`] and [`NativeAndAssets`]. /// -/// Should be kept updated to include ALL balances and assets in the runtime. +/// NOTE: Should be kept updated to include ALL balances and assets in the runtime. pub type NativeAndAllAssets = fungibles::UnionOf< PoolAssets, NativeAndNonPoolAssets, @@ -903,9 +904,40 @@ impl pallet_xcm_bridge_hub_router::Config for Runtim type FeeAsset = xcm_config::bridging::XcmBridgeHubRouterFeeAssetId; } +#[cfg(feature = "runtime-benchmarks")] +use crate::fungible::NativeOrWithId; + +#[cfg(feature = "runtime-benchmarks")] +use frame_support::traits::PalletInfoAccess; + +#[cfg(feature = "runtime-benchmarks")] +pub struct PalletAssetRewardsBenchmarkHelper; + +#[cfg(feature = "runtime-benchmarks")] +impl pallet_asset_rewards::benchmarking::BenchmarkHelper + for PalletAssetRewardsBenchmarkHelper +{ + fn to_asset_id(seed: NativeOrWithId) -> xcm::v3::Location { + match seed { + NativeOrWithId::Native => xcm::v3::Location::here().into(), + NativeOrWithId::WithId(id) => xcm::v3::Location::ancestor(id.try_into().unwrap()), + } + } + fn to_account_id(seed: u32) -> AccountId { + let mut bytes = [0u8; 32]; + bytes[0..4].copy_from_slice(&seed.to_be_bytes()); + bytes.into() + } + fn sufficient_asset() -> xcm::v3::Location { + xcm::v3::Junction::PalletInstance(::index() as u8).into() + } +} + parameter_types! { - pub const AssetRewardsPalletId: PalletId = PalletId(*b"py/asrwd"); + pub const AssetRewardsPalletId: PalletId = PalletId(*b"py/astrd"); pub const TreasurerBodyId: BodyId = BodyId::Treasury; + pub TreasurerBodyAccount: AccountId = + AccountIdConversion::::into_account_truncating(&TREASURY_PALLET_ID); } impl pallet_asset_rewards::Config for Runtime { @@ -914,12 +946,13 @@ impl pallet_asset_rewards::Config for Runtime { type Balance = Balance; type Assets = NativeAndAllAssets; type AssetId = xcm::v3::Location; - type PermissionedPoolCreator = EitherOfDiverse< - EnsureRoot, + type PermissionedOrigin = EnsureWithSuccess< EnsureXcm>, + AccountId, + TreasurerBodyAccount, >; #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); + type BenchmarkHelper = PalletAssetRewardsBenchmarkHelper; } // Create the runtime by composing the FRAME pallets that were previously configured. From 7900c4bdc9cfe7d50c3ff60e6abea7a2b6c74f29 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Thu, 11 Apr 2024 15:49:01 +0400 Subject: [PATCH 053/159] asset-hub-rococo benchmarks! --- .../assets/asset-hub-rococo/src/lib.rs | 6 +- .../frame/asset-rewards/src/benchmarking.rs | 76 ++++++++----------- 2 files changed, 36 insertions(+), 46 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index e95d364679c4..6097fb72d052 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -947,7 +947,10 @@ impl pallet_asset_rewards::Config for Runtime { type Assets = NativeAndAllAssets; type AssetId = xcm::v3::Location; type PermissionedOrigin = EnsureWithSuccess< - EnsureXcm>, + EitherOfDiverse< + EnsureRoot, + EnsureXcm>, + >, AccountId, TreasurerBodyAccount, >; @@ -1109,6 +1112,7 @@ mod benches { [pallet_assets, Foreign] [pallet_assets, Pool] [pallet_asset_conversion, AssetConversion] + [pallet_asset_rewards, AssetRewards] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 847385dd412f..e589ecd53121 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -28,7 +28,7 @@ use frame_support::{ EnsureOrigin, }, }; -use frame_system::RawOrigin; +use frame_system::{RawOrigin, RawOrigin::Root}; use sp_runtime::{traits::One, SaturatedConversion}; use sp_std::prelude::*; @@ -102,24 +102,23 @@ mod benchmarks { fn create_pool() { use super::*; - let origin = T::PermissionedOrigin::try_successful_origin().unwrap(); - let acc = T::PermissionedOrigin::ensure_origin(origin.clone()).unwrap(); + let root_acc = T::PermissionedOrigin::ensure_origin(Root.into()).unwrap(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); create_and_mint_asset::( - &acc, + &root_acc, &staked_asset, T::Assets::minimum_balance(staked_asset.clone()), ); create_and_mint_asset::( - &acc, + &root_acc, &reward_asset, T::Assets::minimum_balance(reward_asset.clone()), ); #[extrinsic_call] _( - origin as T::RuntimeOrigin, + Root, Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -129,8 +128,8 @@ mod benchmarks { assert_last_event::( Event::PoolCreated { - creator: acc.clone(), - admin: acc, + creator: root_acc.clone(), + admin: root_acc, staked_asset_id: staked_asset, reward_asset_id: reward_asset, reward_rate_per_block: 100u32.into(), @@ -145,7 +144,6 @@ mod benchmarks { fn stake() { use super::*; - let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); let staker = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); @@ -161,7 +159,7 @@ mod benchmarks { ); assert_ok!(AssetRewards::::create_pool( - permissioned as T::RuntimeOrigin, + Root.into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -181,7 +179,6 @@ mod benchmarks { fn unstake() { use super::*; - let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); let staker = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); @@ -197,7 +194,7 @@ mod benchmarks { ); assert_ok!(AssetRewards::::create_pool( - permissioned as T::RuntimeOrigin, + Root.into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -225,7 +222,6 @@ mod benchmarks { let block_number_before = frame_system::Pallet::::block_number(); - let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); let staker = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); @@ -240,7 +236,7 @@ mod benchmarks { T::Assets::minimum_balance(reward_asset.clone()), ); assert_ok!(AssetRewards::::create_pool( - permissioned, + Root.into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -283,7 +279,6 @@ mod benchmarks { fn set_pool_reward_rate_per_block() { use super::*; - let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); let acc = T::BenchmarkHelper::to_account_id(1); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); @@ -299,7 +294,7 @@ mod benchmarks { ); assert_ok!(AssetRewards::::create_pool( - permissioned.clone() as T::RuntimeOrigin, + Root.into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -308,7 +303,7 @@ mod benchmarks { )); #[extrinsic_call] - _(permissioned as T::RuntimeOrigin, 0u32.into(), 5u32.into()); + _(Root, 0u32.into(), 5u32.into()); assert_last_event::( Event::PoolRewardRateModified { @@ -323,7 +318,6 @@ mod benchmarks { fn set_pool_admin() { use super::*; - let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); let new_admin = T::BenchmarkHelper::to_account_id(2); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); @@ -339,7 +333,7 @@ mod benchmarks { ); assert_ok!(AssetRewards::::create_pool( - permissioned.clone() as T::RuntimeOrigin, + Root.into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -348,7 +342,7 @@ mod benchmarks { )); #[extrinsic_call] - _(permissioned as T::RuntimeOrigin, 0u32.into(), new_admin.clone()); + _(Root, 0u32.into(), new_admin.clone()); assert_last_event::(Event::PoolAdminModified { pool_id: 0u32.into(), new_admin }.into()); } @@ -357,7 +351,6 @@ mod benchmarks { fn set_pool_expiry_block() { use super::*; - let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); let acc = T::BenchmarkHelper::to_account_id(1); @@ -373,7 +366,7 @@ mod benchmarks { ); assert_ok!(AssetRewards::::create_pool( - permissioned.clone() as T::RuntimeOrigin, + Root.into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -382,7 +375,7 @@ mod benchmarks { )); #[extrinsic_call] - _(permissioned as T::RuntimeOrigin, 0u32.into(), 1000u32.into()); + _(Root, 0u32.into(), 1000u32.into()); assert_last_event::( Event::PoolExpiryBlockModified { @@ -397,15 +390,14 @@ mod benchmarks { fn deposit_reward_tokens() { use super::*; - let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); - let permissioned_acc = T::PermissionedOrigin::ensure_origin(permissioned.clone()).unwrap(); + let acc = T::BenchmarkHelper::to_account_id(1); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_and_mint_asset::(&permissioned_acc, &reward_asset, 100_000u32.into()); - create_and_mint_asset::(&permissioned_acc, &staked_asset, 100_000u32.into()); + create_and_mint_asset::(&acc, &reward_asset, 100_000u32.into()); + create_and_mint_asset::(&acc, &staked_asset, 100_000u32.into()); assert_ok!(AssetRewards::::create_pool( - permissioned.clone() as T::RuntimeOrigin, + Root.into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -416,12 +408,12 @@ mod benchmarks { let pool_acc = AssetRewards::::pool_account_id(&0u32).unwrap(); create_and_mint_sufficient::(&pool_acc); - let balance_before = T::Assets::balance(reward_asset.clone(), &permissioned_acc); + let balance_before = T::Assets::balance(reward_asset.clone(), &acc); #[extrinsic_call] - _(RawOrigin::Signed(permissioned_acc.clone()), 0u32.into(), 10_000u32.into()); + _(RawOrigin::Signed(acc.clone()), 0u32.into(), 10_000u32.into()); - let balance_after = T::Assets::balance(reward_asset.clone(), &permissioned_acc); + let balance_after = T::Assets::balance(reward_asset.clone(), &acc); assert_eq!(balance_after, balance_before - 10_000u32.into()); } @@ -430,15 +422,14 @@ mod benchmarks { fn withdraw_reward_tokens() { use super::*; - let permissioned = T::PermissionedOrigin::try_successful_origin().unwrap(); - let permissioned_acc = T::PermissionedOrigin::ensure_origin(permissioned.clone()).unwrap(); + let acc = T::BenchmarkHelper::to_account_id(1); let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - create_and_mint_asset::(&permissioned_acc, &staked_asset, 10000u32.into()); - create_and_mint_asset::(&permissioned_acc, &reward_asset, 10000u32.into()); + create_and_mint_asset::(&acc, &staked_asset, 10000u32.into()); + create_and_mint_asset::(&acc, &reward_asset, 10000u32.into()); assert_ok!(AssetRewards::::create_pool( - permissioned.clone() as T::RuntimeOrigin, + Root.into(), Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), 100u32.into(), @@ -448,23 +439,18 @@ mod benchmarks { let pool_acc = AssetRewards::::pool_account_id(&0u32).unwrap(); create_and_mint_sufficient::(&pool_acc); - let balance_before = T::Assets::balance(reward_asset.clone(), &permissioned_acc); + let balance_before = T::Assets::balance(reward_asset.clone(), &acc); assert_ok!(AssetRewards::::deposit_reward_tokens( - RawOrigin::Signed(permissioned_acc.clone()).into(), + RawOrigin::Signed(acc.clone()).into(), 0u32.into(), 100u32.into() )); #[extrinsic_call] - _( - RawOrigin::Signed(permissioned_acc.clone()), - 0u32.into(), - 50u32.into(), - permissioned_acc.clone(), - ); + _(Root, 0u32.into(), 50u32.into(), acc.clone()); - let balance_after = T::Assets::balance(reward_asset.clone(), &permissioned_acc); + let balance_after = T::Assets::balance(reward_asset.clone(), &acc); // Deposited 100, withdrew 50 assert_eq!(balance_after, balance_before - 50u32.into()); From 7b3209d6a14513c41511685131ad54d65939141b Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Thu, 11 Apr 2024 16:17:00 +0400 Subject: [PATCH 054/159] use correct relay treasury location --- .../runtimes/assets/asset-hub-rococo/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 6097fb72d052..4dccf52c4a45 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -45,6 +45,7 @@ use sp_runtime::{ ApplyExtrinsicResult, Permill, }; use testnet_parachains_constants::rococo::snowbridge::EthereumNetwork; +use xcm_executor::traits::ConvertLocation; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -77,14 +78,14 @@ use parachains_common::{ message_queue::{NarrowOriginToSibling, ParaIdToSibling}, AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, CollectionId, Hash, Header, ItemId, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, NORMAL_DISPATCH_RATIO, - TREASURY_PALLET_ID, }; use sp_runtime::{Perbill, RuntimeDebug}; use testnet_parachains_constants::rococo::{consensus::*, currency::*, fee::WeightToFee, time::*}; use xcm_config::{ ForeignAssetsConvertedConcreteId, ForeignCreatorsSovereignAccountOf, GovernanceLocation, - PoolAssetsConvertedConcreteId, PoolAssetsPalletLocationV3, TokenLocation, TokenLocationV3, - TrustBackedAssetsConvertedConcreteId, TrustBackedAssetsPalletLocationV3, + LocationToAccountId, PoolAssetsConvertedConcreteId, PoolAssetsPalletLocationV3, + RelayTreasuryLocation, TokenLocation, TokenLocationV3, TrustBackedAssetsConvertedConcreteId, + TrustBackedAssetsPalletLocationV3, }; #[cfg(any(feature = "std", test))] @@ -936,8 +937,7 @@ impl pallet_asset_rewards::benchmarking::BenchmarkHelper::into_account_truncating(&TREASURY_PALLET_ID); + pub TreasurerBodyAccount: AccountId = LocationToAccountId::convert_location(&RelayTreasuryLocation::get()).unwrap(); } impl pallet_asset_rewards::Config for Runtime { From b1c36683e5f1c47c2e75ab9a55b756b05cd7526a Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Thu, 11 Apr 2024 16:22:08 +0400 Subject: [PATCH 055/159] add to asset-hub-westend --- Cargo.lock | 1 + .../assets/asset-hub-westend/Cargo.toml | 4 + .../assets/asset-hub-westend/src/lib.rs | 96 ++++++++++++++++--- .../asset-hub-westend/src/xcm_config.rs | 5 +- 4 files changed, 92 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18cf711a69af..127ca605092b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -990,6 +990,7 @@ dependencies = [ "log", "pallet-asset-conversion", "pallet-asset-conversion-tx-payment", + "pallet-asset-rewards", "pallet-assets", "pallet-aura", "pallet-authorship", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml index e25554ec0a5f..ca3b78c707f2 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml @@ -26,6 +26,7 @@ frame-try-runtime = { path = "../../../../../substrate/frame/try-runtime", defau pallet-asset-conversion-tx-payment = { path = "../../../../../substrate/frame/transaction-payment/asset-conversion-tx-payment", default-features = false } pallet-assets = { path = "../../../../../substrate/frame/assets", default-features = false } pallet-asset-conversion = { path = "../../../../../substrate/frame/asset-conversion", default-features = false } +pallet-asset-rewards = { path = "../../../../../substrate/frame/asset-rewards", default-features = false } pallet-aura = { path = "../../../../../substrate/frame/aura", default-features = false } pallet-authorship = { path = "../../../../../substrate/frame/authorship", default-features = false } pallet-balances = { path = "../../../../../substrate/frame/balances", default-features = false } @@ -132,6 +133,7 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", + "pallet-asset-rewards/runtime-benchmarks" ] try-runtime = [ "cumulus-pallet-aura-ext/try-runtime", @@ -164,6 +166,7 @@ try-runtime = [ "parachain-info/try-runtime", "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", + "pallet-asset-rewards/try-runtime" ] std = [ "assets-common/std", @@ -236,6 +239,7 @@ std = [ "xcm-builder/std", "xcm-executor/std", "xcm/std", + "pallet-asset-rewards/std" ] # A feature that should be enabled when the runtime should be built for on-chain 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 c1fb6367312a..64028f911ead 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -29,6 +29,7 @@ pub mod xcm_config; use assets_common::{ local_and_foreign_assets::{LocalFromLeft, TargetFromLeft}, + AssetIdForPoolAssets, AssetIdForPoolAssetsConvertV3Location, AssetIdForTrustBackedAssetsConvert, }; use codec::{Decode, Encode, MaxEncodedLen}; @@ -42,19 +43,19 @@ use frame_support::{ traits::{ fungible, fungibles, tokens::{imbalance::ResolveAssetTo, nonfungibles_v2::Inspect}, - AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Equals, - InstanceFilter, TransformOrigin, + AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, EitherOfDiverse, + Equals, InstanceFilter, TransformOrigin, }, weights::{ConstantMultiplier, Weight}, BoundedVec, PalletId, }; use frame_system::{ limits::{BlockLength, BlockWeights}, - EnsureRoot, EnsureSigned, EnsureSignedBy, + EnsureRoot, EnsureSigned, EnsureSignedBy, EnsureWithSuccess, }; use pallet_asset_conversion_tx_payment::AssetConversionAdapter; use pallet_nfts::{DestroyWitness, PalletFeatures}; -use pallet_xcm::EnsureXcm; +use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; use parachains_common::{ impls::DealWithFees, message_queue::*, AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, CollectionId, Hash, Header, ItemId, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, @@ -74,10 +75,12 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; use testnet_parachains_constants::westend::{consensus::*, currency::*, fee::WeightToFee, time::*}; use xcm_config::{ - ForeignAssetsConvertedConcreteId, PoolAssetsConvertedConcreteId, + ForeignAssetsConvertedConcreteId, GovernanceLocation, LocationToAccountId, + PoolAssetsConvertedConcreteId, PoolAssetsPalletLocationV3, RelayTreasuryLocation, TrustBackedAssetsConvertedConcreteId, TrustBackedAssetsPalletLocationV3, WestendLocation, WestendLocationV3, XcmOriginToTransactDispatchOrigin, }; +use xcm_executor::traits::ConvertLocation; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; @@ -85,16 +88,14 @@ pub use sp_runtime::BuildStorage; use assets_common::{foreign_creators::ForeignCreators, matching::FromSiblingParachain}; use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; // We exclude `Assets` since it's the name of a pallet -use xcm::latest::prelude::AssetId; - +use crate::xcm_config::ForeignCreatorsSovereignAccountOf; +use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; #[cfg(feature = "runtime-benchmarks")] use xcm::latest::prelude::{ Asset, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, NetworkId, NonFungible, Parent, ParentThen, Response, XCM_VERSION, }; - -use crate::xcm_config::ForeignCreatorsSovereignAccountOf; -use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; +use xcm::latest::{prelude::AssetId, BodyId}; impl_opaque_keys! { pub struct SessionKeys { @@ -307,7 +308,7 @@ pub type LocalAndForeignAssets = fungibles::UnionOf< >; /// Union fungibles implementation for [`LocalAndForeignAssets`] and `Balances`. -pub type NativeAndAssets = fungible::UnionOf< +pub type NativeAndNonPoolAssets = fungible::UnionOf< Balances, LocalAndForeignAssets, TargetFromLeft, @@ -315,12 +316,27 @@ pub type NativeAndAssets = fungible::UnionOf< AccountId, >; +/// Union fungibles implementation for [`PoolAssets`] and [`NativeAndAssets`]. +/// +/// NOTE: Should be kept updated to include ALL balances and assets in the runtime. +pub type NativeAndAllAssets = fungibles::UnionOf< + PoolAssets, + NativeAndNonPoolAssets, + LocalFromLeft< + AssetIdForPoolAssetsConvertV3Location, + AssetIdForPoolAssets, + xcm::v3::Location, + >, + xcm::v3::Location, + AccountId, +>; + impl pallet_asset_conversion::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type HigherPrecisionBalance = sp_core::U256; type AssetKind = xcm::v3::Location; - type Assets = NativeAndAssets; + type Assets = NativeAndNonPoolAssets; type PoolId = (Self::AssetKind, Self::AssetKind); type PoolLocator = pallet_asset_conversion::WithFirstAsset; @@ -344,6 +360,60 @@ impl pallet_asset_conversion::Config for Runtime { >; } +#[cfg(feature = "runtime-benchmarks")] +use crate::fungible::NativeOrWithId; + +#[cfg(feature = "runtime-benchmarks")] +use frame_support::traits::PalletInfoAccess; + +#[cfg(feature = "runtime-benchmarks")] +pub struct PalletAssetRewardsBenchmarkHelper; + +#[cfg(feature = "runtime-benchmarks")] +impl pallet_asset_rewards::benchmarking::BenchmarkHelper + for PalletAssetRewardsBenchmarkHelper +{ + fn to_asset_id(seed: NativeOrWithId) -> xcm::v3::Location { + match seed { + NativeOrWithId::Native => xcm::v3::Location::here().into(), + NativeOrWithId::WithId(id) => xcm::v3::Location::ancestor(id.try_into().unwrap()), + } + } + fn to_account_id(seed: u32) -> AccountId { + let mut bytes = [0u8; 32]; + bytes[0..4].copy_from_slice(&seed.to_be_bytes()); + bytes.into() + } + fn sufficient_asset() -> xcm::v3::Location { + xcm::v3::Junction::PalletInstance(::index() as u8).into() + } +} + +parameter_types! { + pub const AssetRewardsPalletId: PalletId = PalletId(*b"py/astrd"); + pub const TreasurerBodyId: BodyId = BodyId::Treasury; + pub TreasurerBodyAccount: AccountId = LocationToAccountId::convert_location(&RelayTreasuryLocation::get()).unwrap(); + // AccountIdConversion::::into_account_truncating(&RelayTreasuryLocation::get()); +} + +impl pallet_asset_rewards::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type PalletId = AssetRewardsPalletId; + type Balance = Balance; + type Assets = NativeAndAllAssets; + type AssetId = xcm::v3::Location; + type PermissionedOrigin = EnsureWithSuccess< + EitherOfDiverse< + EnsureRoot, + EnsureXcm>, + >, + AccountId, + TreasurerBodyAccount, + >; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = PalletAssetRewardsBenchmarkHelper; +} + parameter_types! { // we just reuse the same deposits pub const ForeignAssetsAssetDeposit: Balance = AssetDeposit::get(); @@ -906,6 +976,7 @@ construct_runtime!( NftFractionalization: pallet_nft_fractionalization = 54, PoolAssets: pallet_assets:: = 55, AssetConversion: pallet_asset_conversion = 56, + AssetRewards: pallet_asset_rewards = 57, } ); @@ -1071,6 +1142,7 @@ mod benches { [pallet_assets, Foreign] [pallet_assets, Pool] [pallet_asset_conversion, AssetConversion] + [pallet_asset_rewards, AssetRewards] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index 360b1a7055b7..b92419899395 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -63,6 +63,7 @@ parameter_types! { pub const WestendLocation: Location = Location::parent(); pub const WestendLocationV3: xcm::v3::Location = xcm::v3::Location::parent(); pub const RelayNetwork: Option = Some(NetworkId::Westend); + pub const GovernanceLocation: Location = Location::parent(); pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); pub UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(ParachainInfo::parachain_id().into())].into(); @@ -601,12 +602,12 @@ impl xcm_executor::Config for XcmConfig { WestendLocationV3, crate::AssetConversion, WeightToFee, - crate::NativeAndAssets, + crate::NativeAndNonPoolAssets, ( TrustBackedAssetsAsLocation, ForeignAssetsConvertedConcreteId, ), - ResolveAssetTo, + ResolveAssetTo, AccountId, >, // This trader allows to pay with `is_sufficient=true` "Trust Backed" assets from dedicated From 77bd1bcb177ab827dca15166209895a7b0d55fee Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Thu, 11 Apr 2024 16:25:12 +0400 Subject: [PATCH 056/159] cleanup --- cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs | 1 - 1 file changed, 1 deletion(-) 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 64028f911ead..8cd1cfcfaff8 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -393,7 +393,6 @@ parameter_types! { pub const AssetRewardsPalletId: PalletId = PalletId(*b"py/astrd"); pub const TreasurerBodyId: BodyId = BodyId::Treasury; pub TreasurerBodyAccount: AccountId = LocationToAccountId::convert_location(&RelayTreasuryLocation::get()).unwrap(); - // AccountIdConversion::::into_account_truncating(&RelayTreasuryLocation::get()); } impl pallet_asset_rewards::Config for Runtime { From 0ef2eaa2c062ca6c833552221c8de6d9f4ad7006 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Thu, 11 Apr 2024 12:52:00 +0000 Subject: [PATCH 057/159] ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=asset-hub-rococo --runtime_dir=assets --target_dir=cumulus --pallet=pallet_asset_rewards --- .../src/weights/pallet_asset_rewards.rs | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs new file mode 100644 index 000000000000..e6eca9176ff5 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs @@ -0,0 +1,183 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Autogenerated weights for `pallet_asset_rewards` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-04-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_asset_rewards +// --chain=asset-hub-rococo-dev +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_asset_rewards`. +pub struct WeightInfo(PhantomData); +impl pallet_asset_rewards::WeightInfo for WeightInfo { + /// Storage: `ForeignAssets::Asset` (r:1 w:0) + /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::NextPoolId` (r:1 w:1) + /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::Pools` (r:0 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn create_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `189` + // Estimated: `4273` + // Minimum execution time: 15_379_000 picoseconds. + Weight::from_parts(16_182_000, 0) + .saturating_add(Weight::from_parts(0, 4273)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn stake() -> Weight { + // Proof Size summary in bytes: + // Measured: `242` + // Estimated: `3707` + // Minimum execution time: 18_711_000 picoseconds. + Weight::from_parts(19_313_000, 0) + .saturating_add(Weight::from_parts(0, 3707)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn unstake() -> Weight { + // Proof Size summary in bytes: + // Measured: `382` + // Estimated: `3847` + // Minimum execution time: 22_244_000 picoseconds. + Weight::from_parts(22_756_000, 0) + .saturating_add(Weight::from_parts(0, 3847)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:0) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ForeignAssets::Asset` (r:1 w:1) + /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) + /// Storage: `ForeignAssets::Account` (r:2 w:2) + /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) + fn harvest_rewards() -> Weight { + // Proof Size summary in bytes: + // Measured: `880` + // Estimated: `7404` + // Minimum execution time: 63_048_000 picoseconds. + Weight::from_parts(64_136_000, 0) + .saturating_add(Weight::from_parts(0, 7404)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_pool_reward_rate_per_block() -> Weight { + // Proof Size summary in bytes: + // Measured: `242` + // Estimated: `3707` + // Minimum execution time: 14_068_000 picoseconds. + Weight::from_parts(14_396_000, 0) + .saturating_add(Weight::from_parts(0, 3707)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_pool_admin() -> Weight { + // Proof Size summary in bytes: + // Measured: `242` + // Estimated: `3707` + // Minimum execution time: 13_948_000 picoseconds. + Weight::from_parts(14_414_000, 0) + .saturating_add(Weight::from_parts(0, 3707)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_pool_expiry_block() -> Weight { + // Proof Size summary in bytes: + // Measured: `242` + // Estimated: `3707` + // Minimum execution time: 14_677_000 picoseconds. + Weight::from_parts(15_052_000, 0) + .saturating_add(Weight::from_parts(0, 3707)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:0) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ForeignAssets::Asset` (r:1 w:1) + /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) + /// Storage: `ForeignAssets::Account` (r:2 w:2) + /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn deposit_reward_tokens() -> Weight { + // Proof Size summary in bytes: + // Measured: `766` + // Estimated: `7404` + // Minimum execution time: 52_312_000 picoseconds. + Weight::from_parts(53_272_000, 0) + .saturating_add(Weight::from_parts(0, 7404)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:0) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ForeignAssets::Asset` (r:1 w:1) + /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) + /// Storage: `ForeignAssets::Account` (r:2 w:2) + /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) + fn withdraw_reward_tokens() -> Weight { + // Proof Size summary in bytes: + // Measured: `740` + // Estimated: `7404` + // Minimum execution time: 50_015_000 picoseconds. + Weight::from_parts(51_033_000, 0) + .saturating_add(Weight::from_parts(0, 7404)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } +} From 4a65a38d495d48e79d41dc01e31816a7a77adb8e Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Thu, 11 Apr 2024 13:36:27 +0000 Subject: [PATCH 058/159] ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=asset-hub-westend --runtime_dir=assets --target_dir=cumulus --pallet=pallet_asset_rewards --- .../src/weights/pallet_asset_rewards.rs | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs new file mode 100644 index 000000000000..3f9a03b82e25 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs @@ -0,0 +1,183 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Autogenerated weights for `pallet_asset_rewards` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-04-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_asset_rewards +// --chain=asset-hub-westend-dev +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_asset_rewards`. +pub struct WeightInfo(PhantomData); +impl pallet_asset_rewards::WeightInfo for WeightInfo { + /// Storage: `ForeignAssets::Asset` (r:1 w:0) + /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::NextPoolId` (r:1 w:1) + /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::Pools` (r:0 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn create_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `189` + // Estimated: `4273` + // Minimum execution time: 16_850_000 picoseconds. + Weight::from_parts(17_383_000, 0) + .saturating_add(Weight::from_parts(0, 4273)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn stake() -> Weight { + // Proof Size summary in bytes: + // Measured: `242` + // Estimated: `3707` + // Minimum execution time: 19_374_000 picoseconds. + Weight::from_parts(19_732_000, 0) + .saturating_add(Weight::from_parts(0, 3707)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn unstake() -> Weight { + // Proof Size summary in bytes: + // Measured: `382` + // Estimated: `3847` + // Minimum execution time: 22_934_000 picoseconds. + Weight::from_parts(23_471_000, 0) + .saturating_add(Weight::from_parts(0, 3847)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:0) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ForeignAssets::Asset` (r:1 w:1) + /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) + /// Storage: `ForeignAssets::Account` (r:2 w:2) + /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) + fn harvest_rewards() -> Weight { + // Proof Size summary in bytes: + // Measured: `880` + // Estimated: `7404` + // Minimum execution time: 62_531_000 picoseconds. + Weight::from_parts(63_845_000, 0) + .saturating_add(Weight::from_parts(0, 7404)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_pool_reward_rate_per_block() -> Weight { + // Proof Size summary in bytes: + // Measured: `242` + // Estimated: `3707` + // Minimum execution time: 15_120_000 picoseconds. + Weight::from_parts(15_579_000, 0) + .saturating_add(Weight::from_parts(0, 3707)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_pool_admin() -> Weight { + // Proof Size summary in bytes: + // Measured: `242` + // Estimated: `3707` + // Minimum execution time: 14_979_000 picoseconds. + Weight::from_parts(15_414_000, 0) + .saturating_add(Weight::from_parts(0, 3707)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_pool_expiry_block() -> Weight { + // Proof Size summary in bytes: + // Measured: `242` + // Estimated: `3707` + // Minimum execution time: 16_097_000 picoseconds. + Weight::from_parts(18_616_000, 0) + .saturating_add(Weight::from_parts(0, 3707)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:0) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ForeignAssets::Asset` (r:1 w:1) + /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) + /// Storage: `ForeignAssets::Account` (r:2 w:2) + /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn deposit_reward_tokens() -> Weight { + // Proof Size summary in bytes: + // Measured: `766` + // Estimated: `7404` + // Minimum execution time: 52_754_000 picoseconds. + Weight::from_parts(53_628_000, 0) + .saturating_add(Weight::from_parts(0, 7404)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: `AssetRewards::Pools` (r:1 w:0) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ForeignAssets::Asset` (r:1 w:1) + /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) + /// Storage: `ForeignAssets::Account` (r:2 w:2) + /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) + fn withdraw_reward_tokens() -> Weight { + // Proof Size summary in bytes: + // Measured: `740` + // Estimated: `7404` + // Minimum execution time: 50_724_000 picoseconds. + Weight::from_parts(51_570_000, 0) + .saturating_add(Weight::from_parts(0, 7404)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } +} From 29b59d79d2e116587a7950f91a2a18106519b1ab Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 12 Apr 2024 09:58:13 +0400 Subject: [PATCH 059/159] cleaner benchmarkhelper --- .../assets/asset-hub-rococo/src/lib.rs | 23 ++---- .../assets/asset-hub-westend/src/lib.rs | 23 ++---- substrate/bin/node/runtime/src/lib.rs | 14 ++-- .../frame/asset-rewards/src/benchmarking.rs | 78 +++++++------------ substrate/frame/asset-rewards/src/mock.rs | 22 +++++- 5 files changed, 75 insertions(+), 85 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 4dccf52c4a45..f7194f15d77a 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -102,6 +102,9 @@ use xcm::latest::prelude::{ }; use xcm::latest::prelude::{AssetId, BodyId}; +#[cfg(feature = "runtime-benchmarks")] +use frame_support::traits::PalletInfoAccess; + use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; impl_opaque_keys! { @@ -905,12 +908,6 @@ impl pallet_xcm_bridge_hub_router::Config for Runtim type FeeAsset = xcm_config::bridging::XcmBridgeHubRouterFeeAssetId; } -#[cfg(feature = "runtime-benchmarks")] -use crate::fungible::NativeOrWithId; - -#[cfg(feature = "runtime-benchmarks")] -use frame_support::traits::PalletInfoAccess; - #[cfg(feature = "runtime-benchmarks")] pub struct PalletAssetRewardsBenchmarkHelper; @@ -918,16 +915,12 @@ pub struct PalletAssetRewardsBenchmarkHelper; impl pallet_asset_rewards::benchmarking::BenchmarkHelper for PalletAssetRewardsBenchmarkHelper { - fn to_asset_id(seed: NativeOrWithId) -> xcm::v3::Location { - match seed { - NativeOrWithId::Native => xcm::v3::Location::here().into(), - NativeOrWithId::WithId(id) => xcm::v3::Location::ancestor(id.try_into().unwrap()), - } + fn to_asset_id(seed: u32) -> xcm::v3::Location { + // Any Location is fine for benchmarking. + xcm::v3::Location::ancestor(seed.try_into().unwrap()) } - fn to_account_id(seed: u32) -> AccountId { - let mut bytes = [0u8; 32]; - bytes[0..4].copy_from_slice(&seed.to_be_bytes()); - bytes.into() + fn to_account_id(seed: [u8; 32]) -> AccountId { + seed.into() } fn sufficient_asset() -> xcm::v3::Location { xcm::v3::Junction::PalletInstance(::index() as u8).into() 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 8cd1cfcfaff8..970d3a4717f7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -97,6 +97,9 @@ use xcm::latest::prelude::{ }; use xcm::latest::{prelude::AssetId, BodyId}; +#[cfg(feature = "runtime-benchmarks")] +use frame_support::traits::PalletInfoAccess; + impl_opaque_keys! { pub struct SessionKeys { pub aura: Aura, @@ -360,12 +363,6 @@ impl pallet_asset_conversion::Config for Runtime { >; } -#[cfg(feature = "runtime-benchmarks")] -use crate::fungible::NativeOrWithId; - -#[cfg(feature = "runtime-benchmarks")] -use frame_support::traits::PalletInfoAccess; - #[cfg(feature = "runtime-benchmarks")] pub struct PalletAssetRewardsBenchmarkHelper; @@ -373,16 +370,12 @@ pub struct PalletAssetRewardsBenchmarkHelper; impl pallet_asset_rewards::benchmarking::BenchmarkHelper for PalletAssetRewardsBenchmarkHelper { - fn to_asset_id(seed: NativeOrWithId) -> xcm::v3::Location { - match seed { - NativeOrWithId::Native => xcm::v3::Location::here().into(), - NativeOrWithId::WithId(id) => xcm::v3::Location::ancestor(id.try_into().unwrap()), - } + fn to_asset_id(seed: u32) -> xcm::v3::Location { + // Any Location is fine for benchmarking. + xcm::v3::Location::ancestor(seed.try_into().unwrap()) } - fn to_account_id(seed: u32) -> AccountId { - let mut bytes = [0u8; 32]; - bytes[0..4].copy_from_slice(&seed.to_be_bytes()); - bytes.into() + fn to_account_id(seed: [u8; 32]) -> AccountId { + seed.into() } fn sufficient_asset() -> xcm::v3::Location { xcm::v3::Junction::PalletInstance(::index() as u8).into() diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 3757059c1d8f..af63ffe8f337 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1742,13 +1742,15 @@ pub struct AssetRewardsBenchmarkHelper; impl pallet_asset_rewards::benchmarking::BenchmarkHelper, AccountId> for AssetRewardsBenchmarkHelper { - fn to_asset_id(seed: NativeOrWithId) -> NativeOrWithId { - seed + fn to_asset_id(seed: u32) -> NativeOrWithId { + if seed == 0 { + NativeOrWithId::::Native + } else { + NativeOrWithId::::WithId(seed) + } } - fn to_account_id(seed: u32) -> AccountId { - let mut bytes = [0u8; 32]; // Create a 32-byte array filled with zeros - bytes[0..4].copy_from_slice(&seed.to_be_bytes()); // Place the u32 value at the beginning (big-endian for this example) - bytes.into() + fn to_account_id(seed: [u8; 32]) -> AccountId { + seed.into() } fn sufficient_asset() -> NativeOrWithId { NativeOrWithId::::Native diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index e589ecd53121..187a04e3de4c 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -23,7 +23,6 @@ use frame_benchmarking::v2::*; use frame_support::{ assert_ok, traits::{ - fungible::NativeOrWithId, fungibles::{Create, Inspect, Mutate}, EnsureOrigin, }, @@ -34,30 +33,14 @@ use sp_std::prelude::*; /// Benchmark Helper pub trait BenchmarkHelper { - /// Convert a NativeOrWithId to an AssetId - fn to_asset_id(seed: NativeOrWithId) -> AssetId; - /// Convert a u32 to an AccountId - fn to_account_id(seed: u32) -> AccountId; + /// Convert a u32 to an AssetId + fn to_asset_id(seed: u32) -> AssetId; + /// Convert a [u8; 32] to an AccountId + fn to_account_id(seed: [u8; 32]) -> AccountId; /// Return the ID of the asset whos minimum balance is sufficient for an account to exist fn sufficient_asset() -> AssetId; } -impl BenchmarkHelper for () -where - AssetId: From>, - AccountId: From, -{ - fn to_asset_id(seed: NativeOrWithId) -> AssetId { - seed.into() - } - fn to_account_id(seed: u32) -> AccountId { - seed.into() - } - fn sufficient_asset() -> AssetId { - NativeOrWithId::Native.into() - } -} - /// Create and mint the minimum amount of the sufficient asset. fn create_and_mint_sufficient(caller: &T::AccountId) where @@ -103,8 +86,8 @@ mod benchmarks { use super::*; let root_acc = T::PermissionedOrigin::ensure_origin(Root.into()).unwrap(); - let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); - let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); + let staked_asset = T::BenchmarkHelper::to_asset_id(1); + let reward_asset = T::BenchmarkHelper::to_asset_id(2); create_and_mint_asset::( &root_acc, &staked_asset, @@ -144,9 +127,9 @@ mod benchmarks { fn stake() { use super::*; - let staker = T::BenchmarkHelper::to_account_id(2); - let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); - let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); + let staker = T::BenchmarkHelper::to_account_id([1u8; 32]); + let staked_asset = T::BenchmarkHelper::to_asset_id(1); + let reward_asset = T::BenchmarkHelper::to_asset_id(0); create_and_mint_asset::( &staker, &staked_asset, @@ -179,9 +162,9 @@ mod benchmarks { fn unstake() { use super::*; - let staker = T::BenchmarkHelper::to_account_id(2); - let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); - let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); + let staker = T::BenchmarkHelper::to_account_id([1u8; 32]); + let staked_asset = T::BenchmarkHelper::to_asset_id(1); + let reward_asset = T::BenchmarkHelper::to_asset_id(0); create_and_mint_asset::( &staker, &staked_asset, @@ -221,10 +204,9 @@ mod benchmarks { use super::*; let block_number_before = frame_system::Pallet::::block_number(); - - let staker = T::BenchmarkHelper::to_account_id(2); - let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); - let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); + let staker = T::BenchmarkHelper::to_account_id([2u8; 32]); + let staked_asset = T::BenchmarkHelper::to_asset_id(1); + let reward_asset = T::BenchmarkHelper::to_asset_id(2); create_and_mint_asset::( &staker, &staked_asset, @@ -279,9 +261,9 @@ mod benchmarks { fn set_pool_reward_rate_per_block() { use super::*; - let acc = T::BenchmarkHelper::to_account_id(1); - let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); - let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); + let acc = T::BenchmarkHelper::to_account_id([3u8; 32]); + let staked_asset = T::BenchmarkHelper::to_asset_id(1); + let reward_asset = T::BenchmarkHelper::to_asset_id(5); create_and_mint_asset::( &acc, &staked_asset, @@ -318,9 +300,9 @@ mod benchmarks { fn set_pool_admin() { use super::*; - let new_admin = T::BenchmarkHelper::to_account_id(2); - let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); - let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); + let new_admin = T::BenchmarkHelper::to_account_id([2u8; 32]); + let staked_asset = T::BenchmarkHelper::to_asset_id(1); + let reward_asset = T::BenchmarkHelper::to_asset_id(0); create_and_mint_asset::( &new_admin, &staked_asset, @@ -351,9 +333,9 @@ mod benchmarks { fn set_pool_expiry_block() { use super::*; - let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); - let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); - let acc = T::BenchmarkHelper::to_account_id(1); + let staked_asset = T::BenchmarkHelper::to_asset_id(2); + let reward_asset = T::BenchmarkHelper::to_asset_id(5); + let acc = T::BenchmarkHelper::to_account_id([5u8; 32]); create_and_mint_asset::( &acc, &staked_asset, @@ -390,9 +372,9 @@ mod benchmarks { fn deposit_reward_tokens() { use super::*; - let acc = T::BenchmarkHelper::to_account_id(1); - let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); - let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); + let acc = T::BenchmarkHelper::to_account_id([3u8; 32]); + let staked_asset = T::BenchmarkHelper::to_asset_id(1); + let reward_asset = T::BenchmarkHelper::to_asset_id(4); create_and_mint_asset::(&acc, &reward_asset, 100_000u32.into()); create_and_mint_asset::(&acc, &staked_asset, 100_000u32.into()); @@ -422,9 +404,9 @@ mod benchmarks { fn withdraw_reward_tokens() { use super::*; - let acc = T::BenchmarkHelper::to_account_id(1); - let staked_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::WithId(1)); - let reward_asset = T::BenchmarkHelper::to_asset_id(NativeOrWithId::Native); + let acc = T::BenchmarkHelper::to_account_id([3u8; 32]); + let staked_asset = T::BenchmarkHelper::to_asset_id(1); + let reward_asset = T::BenchmarkHelper::to_asset_id(2); create_and_mint_asset::(&acc, &staked_asset, 10000u32.into()); create_and_mint_asset::(&acc, &reward_asset, 10000u32.into()); diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index dad428c4d44a..a5cab540997f 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -17,6 +17,7 @@ //! Test environment for Staking Rewards pallet. +use self::benchmarking::BenchmarkHelper; use super::*; use crate as pallet_staking_rewards; use core::default::Default; @@ -119,6 +120,25 @@ impl EnsureOrigin for MockPermissionedOrigin { pub type NativeAndAssets = UnionOf, u128>; +pub struct AssetRewardsBenchmarkHelper; +impl BenchmarkHelper, u128> for AssetRewardsBenchmarkHelper { + fn to_asset_id(seed: u32) -> NativeOrWithId { + if seed == 0 { + NativeOrWithId::::Native + } else { + NativeOrWithId::::WithId(seed) + } + } + fn to_account_id(seed: [u8; 32]) -> u128 { + // only 16 bytes fit into u128 + let bytes = <[u8; 16]>::try_from(&seed[0..16]).unwrap(); + u128::from_be_bytes(bytes) + } + fn sufficient_asset() -> NativeOrWithId { + NativeOrWithId::::Native + } +} + impl Config for MockRuntime { type RuntimeEvent = RuntimeEvent; type AssetId = NativeOrWithId; @@ -127,7 +147,7 @@ impl Config for MockRuntime { type PalletId = StakingRewardsPalletId; type PermissionedOrigin = MockPermissionedOrigin; #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); + type BenchmarkHelper = AssetRewardsBenchmarkHelper; } pub(crate) fn new_test_ext() -> sp_io::TestExternalities { From 8513adbb07f209ce0e110f4a443fc2ce7fffd7e2 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 12 Apr 2024 10:21:07 +0400 Subject: [PATCH 060/159] feature gate --- substrate/frame/asset-rewards/src/mock.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index a5cab540997f..765c4595529a 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -17,7 +17,6 @@ //! Test environment for Staking Rewards pallet. -use self::benchmarking::BenchmarkHelper; use super::*; use crate as pallet_staking_rewards; use core::default::Default; @@ -34,6 +33,9 @@ use frame_support::{ use frame_system::EnsureSigned; use sp_runtime::{traits::IdentityLookup, BuildStorage}; +#[cfg(feature = "runtime-benchmarks")] +use self::benchmarking::BenchmarkHelper; + type Block = frame_system::mocking::MockBlock; construct_runtime!( @@ -120,7 +122,9 @@ impl EnsureOrigin for MockPermissionedOrigin { pub type NativeAndAssets = UnionOf, u128>; +#[cfg(feature = "runtime-benchmarks")] pub struct AssetRewardsBenchmarkHelper; +#[cfg(feature = "runtime-benchmarks")] impl BenchmarkHelper, u128> for AssetRewardsBenchmarkHelper { fn to_asset_id(seed: u32) -> NativeOrWithId { if seed == 0 { From ffefda83e926ee3083fcfb5881646df9dcca3801 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 12 Apr 2024 10:39:11 +0400 Subject: [PATCH 061/159] update docs --- .../frame/asset-rewards/src/benchmarking.rs | 2 + substrate/frame/asset-rewards/src/lib.rs | 40 ++++++++++--------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 187a04e3de4c..278c2a2e7bff 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -16,6 +16,8 @@ // limitations under the License. //! Asset Rewards pallet benchmarking. +//! +//! Note: these benchmarks assume that Root passes the `PermissionedOrigin` checks. use super::*; use crate::Pallet as AssetRewards; diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 424e0b0d87be..1bb3cdce8f67 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -17,28 +17,29 @@ //! # FRAME Staking Rewards Pallet //! -//! Allows rewarding fungible token holders. +//! Allows accounts to be rewarded for holding `fungible` asset/s, for example LP tokens. //! //! ## Overview //! -//! Governance can create a new incentive program for a fungible asset by creating a new pool. +//! A permissioned origin can initiate an incentive program for a fungible asset by creating a new +//! pool. //! -//! When creating the pool, governance specifies a 'staking asset', 'reward asset', 'reward rate -//! per block', and an 'expiry block'. +//! During pool creation, a 'staking asset', 'reward asset', 'reward rate per block', 'expiry +//! block', and 'admin' are specified. By default, the permissioned origin is the admin. //! -//! Once the pool is created, holders of the 'staking asset' can stake them in this pallet, which -//! puts a Freeze on the asset. +//! Once created, holders of the 'staking asset' can 'stake' them in a corresponding pool, which +//! creates a Freeze on the asset. //! -//! Once staked, the staker begins accumulating the right to claim the 'reward asset' each block, +//! Once staked, the rewards denominated in 'reward asset' begin accumulating to the staker, //! proportional to their share of the total staked tokens in the pool. //! -//! Reward assets pending distribution are held in an account derived from the pallet ID and a -//! unique pool ID. +//! Reward assets pending distribution are held in an account unique to each pool. //! -//! Care should be taken to keep pool accounts adequately funded with the reward asset. +//! Care should be taken by the pool operator to keep pool accounts adequately funded with the +//! reward asset. //! -//! The pool administator can adjust the reward rate per block, the expiry block, and the admin -//! after the pool is created. +//! The pool admin may adjust the pool configuration such as reward rate per block, expiry block, +//! and admin. //! //! ## Permissioning //! @@ -46,14 +47,17 @@ //! //! Future iterations of this pallet may allow permissionless creation and management of pools. //! +//! Note: The permissioned origin must return an AccountId. This can be achieved for any Origin by +//! wrapping it with `EnsureSuccess`. +//! //! ## Implementation Notes //! //! Internal logic functions such as `update_pool_and_staker_rewards` where deliberately written -//! without any side-effects like storage interaction. +//! without storage interaction. //! //! Storage interaction such as reads and writes are instead all performed in the top level //! pallet Call method, which while slightly more verbose, makes it much easier to understand the -//! code and reason about where side-effects occur in the pallet. +//! code and reason about how storage reads and writes occur in the pallet. //! //! ## Rewards Algorithm //! @@ -63,15 +67,13 @@ //! Rewards are calculated JIT (just-in-time), and all operations are O(1) making the approach //! scalable to many pools and stakers. //! -//! The approach is widly used across the Ethereum ecosystem, there is also quite battle tested. -//! //! ### Resources //! -//! - [This YouTube video series](https://www.youtube.com/watch?v=6ZO5aYg1GI8), which walks through -//! the math of the algorithm. +//! - [This video series](https://www.youtube.com/watch?v=6ZO5aYg1GI8), which walks through the math +//! of the algorithm. //! - [This dev.to article](https://dev.to/heymarkkop/understanding-sushiswaps-masterchef-staking-rewards-1m6f), //! which explains the algorithm of the SushiSwap MasterChef staking. While not identical to the -//! Synthetix approach, they are very similar. +//! Synthetix approach, they are quite similar. #![deny(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] From 531d766f07f19c4a1205094c1ac0e16a28b84bd8 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 12 Apr 2024 11:01:46 +0400 Subject: [PATCH 062/159] tidy up --- .../assets/asset-hub-rococo/src/lib.rs | 1 + .../asset-hub-rococo/src/weights/mod.rs | 1 + .../assets/asset-hub-westend/src/lib.rs | 1 + .../asset-hub-westend/src/weights/mod.rs | 1 + substrate/frame/asset-rewards/src/lib.rs | 79 ++++++++++--------- substrate/frame/asset-rewards/src/mock.rs | 1 + 6 files changed, 45 insertions(+), 39 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index f7194f15d77a..9c39815d2be3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -947,6 +947,7 @@ impl pallet_asset_rewards::Config for Runtime { AccountId, TreasurerBodyAccount, >; + type WeightInfo = weights::pallet_asset_rewards::WeightInfo; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = PalletAssetRewardsBenchmarkHelper; } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs index fa9e86102c61..ba085a039f2c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs @@ -20,6 +20,7 @@ pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; pub mod pallet_asset_conversion; +pub mod pallet_asset_rewards; pub mod pallet_assets_foreign; pub mod pallet_assets_local; pub mod pallet_assets_pool; 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 970d3a4717f7..4b4115783b23 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -402,6 +402,7 @@ impl pallet_asset_rewards::Config for Runtime { AccountId, TreasurerBodyAccount, >; + type WeightInfo = weights::pallet_asset_rewards::WeightInfo; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = PalletAssetRewardsBenchmarkHelper; } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs index 2f1fcfb05f39..0909d9611425 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs @@ -19,6 +19,7 @@ pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; pub mod pallet_asset_conversion; +pub mod pallet_asset_rewards; pub mod pallet_assets_foreign; pub mod pallet_assets_local; pub mod pallet_assets_pool; diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 1bb3cdce8f67..18e8a852acfb 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -30,7 +30,7 @@ //! Once created, holders of the 'staking asset' can 'stake' them in a corresponding pool, which //! creates a Freeze on the asset. //! -//! Once staked, the rewards denominated in 'reward asset' begin accumulating to the staker, +//! Once staked, rewards denominated in 'reward asset' begin accumulating to the staker, //! proportional to their share of the total staked tokens in the pool. //! //! Reward assets pending distribution are held in an account unique to each pool. @@ -99,14 +99,17 @@ pub mod benchmarking; mod mock; #[cfg(test)] mod tests; +mod weights; -/// The type of the unique id for each pool. +pub use weights::WeightInfo; + +/// Unique id type for each pool. pub type PoolId = u32; /// Multiplier to maintain precision when calculating rewards. pub(crate) const PRECISION_SCALING_FACTOR: u32 = u32::MAX; -/// Convenience type alias for `PoolInfo`. +/// Convenience alias for `PoolInfo`. pub type PoolInfoFor = PoolInfo< ::AccountId, ::AssetId, @@ -114,7 +117,7 @@ pub type PoolInfoFor = PoolInfo< BlockNumberFor, >; -/// A pool staker. +/// The state of a staker in a pool. #[derive(Debug, Default, Clone, Decode, Encode, MaxEncodedLen, TypeInfo)] pub struct PoolStakerInfo { /// Amount of tokens staked. @@ -125,28 +128,28 @@ pub struct PoolStakerInfo { reward_per_token_paid: Balance, } -/// A staking pool. +/// The state and configuration an incentive pool. #[derive(Debug, Clone, Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] pub struct PoolInfo { - /// The asset that is staked in this pool. + /// The asset staked in this pool. staked_asset_id: AssetId, - /// The asset that is distributed as rewards in this pool. + /// The asset distributed as rewards by this pool. reward_asset_id: AssetId, - /// The amount of tokens distributed per block. + /// The amount of tokens rewarded per block. reward_rate_per_block: Balance, + /// The block the pool will cease distributing rewards. + expiry_block: BlockNumber, + /// The permissioned account that can manage this pool. + admin: AccountId, /// The total amount of tokens staked in this pool. total_tokens_staked: Balance, - /// Total rewards accumulated per token, up to the last time the rewards were updated. + /// Total rewards accumulated per token, up to the `last_update_block`. reward_per_token_stored: Balance, - /// Last block number the pool was updated. Used when calculating payouts. + /// Last block number the pool was updated. last_update_block: BlockNumber, - /// The block the pool will cease distributing rewards. - expiry_block: BlockNumber, - /// Permissioned account that can manage this pool. - admin: AccountId, } -#[frame_support::pallet(dev_mode)] +#[frame_support::pallet] pub mod pallet { use super::*; use frame_support::{ @@ -167,7 +170,7 @@ pub mod pallet { /// Overarching event type. type RuntimeEvent: From> + IsType<::RuntimeEvent>; - /// The pallet's id, used for deriving its sovereign account ID. + /// The pallet's id, used for deriving pool account IDs. #[pallet::constant] type PalletId: Get; @@ -190,9 +193,9 @@ pub mod pallet { + Mutate; /// Weight information for extrinsics in this pallet. - // type WeightInfo: WeightInfo; + type WeightInfo: WeightInfo; - /// The benchmarks need a way to create asset ids from u32s. + /// Helper for benchmarking. #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper: benchmarking::BenchmarkHelper; } @@ -246,7 +249,7 @@ pub mod pallet { }, /// An account harvested some rewards. RewardsHarvested { - /// The extrinsic caller. + /// The caller. who: T::AccountId, /// The staker whos rewards were harvested. staker: T::AccountId, @@ -259,7 +262,7 @@ pub mod pallet { PoolCreated { /// The account that created the pool. creator: T::AccountId, - /// Unique ID for the new pool. + /// The unique ID for the new pool. pool_id: PoolId, /// The staking asset. staked_asset_id: T::AssetId, @@ -272,11 +275,6 @@ pub mod pallet { /// The account allowed to modify the pool. admin: T::AccountId, }, - /// A reward pool was deleted by the admin. - PoolDeleted { - /// The deleted pool id. - pool_id: PoolId, - }, /// A pool reward rate was modified by the admin. PoolRewardRateModified { /// The modified pool. @@ -284,7 +282,7 @@ pub mod pallet { /// The new reward rate per block. new_reward_rate_per_block: T::Balance, }, - /// A pool admin modified by the admin. + /// A pool admin was modified. PoolAdminModified { /// The modified pool. pool_id: PoolId, @@ -306,30 +304,24 @@ pub mod pallet { NotEnoughTokens, /// An operation was attempted on a non-existent pool. NonExistentPool, - /// An operation was attempted on a non-existent pool. + /// An operation was attempted for a non-existent staker. NonExistentStaker, - /// An operation was attempted using a non-existent asset. + /// An operation was attempted with a non-existent asset. NonExistentAsset, /// There was an error converting a block number. BlockNumberConversionError, - /// Expiry block must be in the future. + /// The expiry block must be in the future. ExpiryBlockMustBeInTheFuture, } - #[pallet::hooks] - impl Hooks> for Pallet { - fn integrity_test() { - // TODO: Proper implementation - } - } - /// Pallet's callable functions. /// /// Allows optionally specifying an admin account for the pool. By default, the origin is made /// admin. - #[pallet::call] + #[pallet::call(weight(::WeightInfo))] impl Pallet { /// Create a new reward pool. + #[pallet::call_index(0)] pub fn create_pool( origin: OriginFor, staked_asset_id: Box, @@ -392,6 +384,7 @@ pub mod pallet { } /// Stake tokens in a pool. + #[pallet::call_index(1)] pub fn stake(origin: OriginFor, pool_id: PoolId, amount: T::Balance) -> DispatchResult { let caller = ensure_signed(origin)?; @@ -419,6 +412,7 @@ pub mod pallet { } /// Unstake tokens from a pool. + #[pallet::call_index(2)] pub fn unstake( origin: OriginFor, pool_id: PoolId, @@ -453,6 +447,7 @@ pub mod pallet { } /// Harvest unclaimed pool rewards for a staker. + #[pallet::call_index(3)] pub fn harvest_rewards( origin: OriginFor, pool_id: PoolId, @@ -495,6 +490,7 @@ pub mod pallet { } /// Modify a pool reward rate. + #[pallet::call_index(4)] pub fn set_pool_reward_rate_per_block( origin: OriginFor, pool_id: PoolId, @@ -521,6 +517,7 @@ pub mod pallet { } /// Modify a pool admin. + #[pallet::call_index(5)] pub fn set_pool_admin( origin: OriginFor, pool_id: PoolId, @@ -540,6 +537,7 @@ pub mod pallet { } /// Modify a expiry block. + #[pallet::call_index(6)] pub fn set_pool_expiry_block( origin: OriginFor, pool_id: PoolId, @@ -571,6 +569,7 @@ pub mod pallet { /// This method is not strictly necessary (tokens could be transferred directly to the /// pool pot address), but is provided for convenience so manual derivation of the /// account id is not required. + #[pallet::call_index(7)] pub fn deposit_reward_tokens( origin: OriginFor, pool_id: PoolId, @@ -590,6 +589,7 @@ pub mod pallet { } /// Permissioned method to withdraw reward tokens from a pool. + #[pallet::call_index(8)] pub fn withdraw_reward_tokens( origin: OriginFor, pool_id: PoolId, @@ -601,6 +601,7 @@ pub mod pallet { let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; ensure!(pool_info.admin == caller, BadOrigin); + T::Assets::transfer( pool_info.reward_asset_id, &Self::pool_account_id(&pool_id)?, @@ -661,7 +662,7 @@ pub mod pallet { /// Derives the current reward per token for this pool. /// - /// Helper function for update_pool_rewards. Should not be called directly. + /// This is a helper function for `update_pool_rewards` and should not be called directly. fn reward_per_token(pool_info: &PoolInfoFor) -> Result { if pool_info.total_tokens_staked.eq(&0u32.into()) { return Ok(pool_info.reward_per_token_stored) @@ -687,7 +688,7 @@ pub mod pallet { /// Derives the amount of rewards earned by a staker. /// - /// Helper function for update_pool_rewards. Should not be called directly. + /// This is a helper function for `update_pool_rewards` and should not be called directly. fn derive_rewards( pool_info: &PoolInfoFor, staker_info: &PoolStakerInfo, diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index 765c4595529a..9d5f137913c5 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -150,6 +150,7 @@ impl Config for MockRuntime { type Assets = NativeAndAssets; type PalletId = StakingRewardsPalletId; type PermissionedOrigin = MockPermissionedOrigin; + type WeightInfo = (); #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = AssetRewardsBenchmarkHelper; } From c7e8999d3e1003ae772c30e00c5f042e0e80ffa4 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 12 Apr 2024 17:04:14 +1000 Subject: [PATCH 063/159] Update substrate/frame/asset-rewards/src/mock.rs --- substrate/frame/asset-rewards/src/mock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index 9d5f137913c5..32f1c7913d9e 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Test environment for Staking Rewards pallet. +//! Test environment for Asset Rewards pallet. use super::*; use crate as pallet_staking_rewards; From 36e1e7d48b70e25cddf374a0304fd651a98b2ea5 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 12 Apr 2024 17:05:42 +1000 Subject: [PATCH 064/159] Update substrate/frame/asset-rewards/src/tests.rs --- substrate/frame/asset-rewards/src/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index efa4c9676f45..220241263682 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -32,7 +32,7 @@ const DEFAULT_ADMIN: u128 = 1; /// - Expiry block: 100 /// - Admin: 1 /// -/// Useful to reduce boilerplate in tests when it's not important to customise or reusing pool +/// Useful to reduce boilerplate in tests when it's not important to customise or reuse pool /// params. pub fn create_default_pool() { assert_ok!(StakingRewards::create_pool( From ae1764981de0d8afa2f9306f85811d2c0b70d87e Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 12 Apr 2024 17:09:23 +1000 Subject: [PATCH 065/159] Update substrate/frame/asset-rewards/src/tests.rs --- substrate/frame/asset-rewards/src/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 220241263682..27ff29833912 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -368,7 +368,7 @@ mod stake { #[test] fn fails_for_insufficient_balance() { - // TODO: When we're able to freeze assets. + // TODO: When freezing assets fails. } } From b56af273a81e3aab9da152ea700de25818fcea27 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 12 Apr 2024 11:11:11 +0400 Subject: [PATCH 066/159] kitchensink weightinfo --- substrate/bin/node/runtime/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index af63ffe8f337..ef533b3cc80d 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1782,6 +1782,7 @@ impl pallet_asset_rewards::Config for Runtime { type Assets = NativeAndAssets; type PalletId = StakingRewardsPalletId; type PermissionedOrigin = AssetRewardsPermissionedOrigin; + type WeightInfo = (); #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = AssetRewardsBenchmarkHelper; } From eaa7fdfd2b2b4d42321403e3aaf24e040c9114b4 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Fri, 12 Apr 2024 07:18:15 +0000 Subject: [PATCH 067/159] ".git/.scripts/commands/fmt/fmt.sh" --- Cargo.toml | 2 +- .../parachains/runtimes/assets/asset-hub-rococo/Cargo.toml | 6 +++--- .../parachains/runtimes/assets/asset-hub-westend/Cargo.toml | 6 +++--- substrate/bin/node/runtime/Cargo.toml | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a235c19c8c3b..a020bfa694a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -301,6 +301,7 @@ members = [ "substrate/frame/alliance", "substrate/frame/asset-conversion", "substrate/frame/asset-rate", + "substrate/frame/asset-rewards", "substrate/frame/assets", "substrate/frame/atomic-swap", "substrate/frame/aura", @@ -392,7 +393,6 @@ members = [ "substrate/frame/session/benchmarking", "substrate/frame/society", "substrate/frame/staking", - "substrate/frame/asset-rewards", "substrate/frame/staking/reward-curve", "substrate/frame/staking/reward-fn", "substrate/frame/staking/runtime-api", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml index 035ca061af1f..f894bba6d7ff 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml @@ -122,6 +122,7 @@ runtime-benchmarks = [ "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", + "pallet-asset-rewards/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", @@ -144,7 +145,6 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", - "pallet-asset-rewards/runtime-benchmarks" ] try-runtime = [ "cumulus-pallet-aura-ext/try-runtime", @@ -157,6 +157,7 @@ try-runtime = [ "frame-try-runtime/try-runtime", "pallet-asset-conversion-tx-payment/try-runtime", "pallet-asset-conversion/try-runtime", + "pallet-asset-rewards/try-runtime", "pallet-assets/try-runtime", "pallet-aura/try-runtime", "pallet-authorship/try-runtime", @@ -178,7 +179,6 @@ try-runtime = [ "parachain-info/try-runtime", "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", - "pallet-asset-rewards/try-runtime" ] std = [ "assets-common/std", @@ -206,6 +206,7 @@ std = [ "log/std", "pallet-asset-conversion-tx-payment/std", "pallet-asset-conversion/std", + "pallet-asset-rewards/std", "pallet-assets/std", "pallet-aura/std", "pallet-authorship/std", @@ -254,7 +255,6 @@ std = [ "xcm-builder/std", "xcm-executor/std", "xcm/std", - "pallet-asset-rewards/std" ] # A feature that should be enabled when the runtime should be built for on-chain diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml index ca3b78c707f2..58f7064cd4a5 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml @@ -113,6 +113,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "hex-literal", "pallet-asset-conversion/runtime-benchmarks", + "pallet-asset-rewards/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", @@ -133,7 +134,6 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", - "pallet-asset-rewards/runtime-benchmarks" ] try-runtime = [ "cumulus-pallet-aura-ext/try-runtime", @@ -146,6 +146,7 @@ try-runtime = [ "frame-try-runtime/try-runtime", "pallet-asset-conversion-tx-payment/try-runtime", "pallet-asset-conversion/try-runtime", + "pallet-asset-rewards/try-runtime", "pallet-assets/try-runtime", "pallet-aura/try-runtime", "pallet-authorship/try-runtime", @@ -166,7 +167,6 @@ try-runtime = [ "parachain-info/try-runtime", "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", - "pallet-asset-rewards/try-runtime" ] std = [ "assets-common/std", @@ -194,6 +194,7 @@ std = [ "log/std", "pallet-asset-conversion-tx-payment/std", "pallet-asset-conversion/std", + "pallet-asset-rewards/std", "pallet-assets/std", "pallet-aura/std", "pallet-authorship/std", @@ -239,7 +240,6 @@ std = [ "xcm-builder/std", "xcm-executor/std", "xcm/std", - "pallet-asset-rewards/std" ] # A feature that should be enabled when the runtime should be built for on-chain diff --git a/substrate/bin/node/runtime/Cargo.toml b/substrate/bin/node/runtime/Cargo.toml index 0257f68a7bd1..ef6fdbf1e363 100644 --- a/substrate/bin/node/runtime/Cargo.toml +++ b/substrate/bin/node/runtime/Cargo.toml @@ -170,6 +170,7 @@ std = [ "pallet-asset-conversion-tx-payment/std", "pallet-asset-conversion/std", "pallet-asset-rate/std", + "pallet-asset-rewards/std", "pallet-asset-tx-payment/std", "pallet-assets/std", "pallet-authority-discovery/std", @@ -270,7 +271,6 @@ std = [ "sp-transaction-pool/std", "sp-version/std", "substrate-wasm-builder", - "pallet-asset-rewards/std" ] runtime-benchmarks = [ "frame-benchmarking-pallet-pov/runtime-benchmarks", @@ -282,6 +282,7 @@ runtime-benchmarks = [ "pallet-alliance/runtime-benchmarks", "pallet-asset-conversion/runtime-benchmarks", "pallet-asset-rate/runtime-benchmarks", + "pallet-asset-rewards/runtime-benchmarks", "pallet-asset-tx-payment/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-babe/runtime-benchmarks", @@ -347,7 +348,6 @@ runtime-benchmarks = [ "pallet-whitelist/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "sp-staking/runtime-benchmarks", - "pallet-asset-rewards/runtime-benchmarks" ] try-runtime = [ "frame-benchmarking-pallet-pov/try-runtime", @@ -360,6 +360,7 @@ try-runtime = [ "pallet-asset-conversion-tx-payment/try-runtime", "pallet-asset-conversion/try-runtime", "pallet-asset-rate/try-runtime", + "pallet-asset-rewards/try-runtime", "pallet-asset-tx-payment/try-runtime", "pallet-assets/try-runtime", "pallet-authority-discovery/try-runtime", @@ -429,7 +430,6 @@ try-runtime = [ "pallet-vesting/try-runtime", "pallet-whitelist/try-runtime", "sp-runtime/try-runtime", - "pallet-asset-rewards/try-runtime" ] experimental = [ "frame-support/experimental", From 1c1646e6ce5d683f61bf1b608cc6ce7fcdcc6d31 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 12 Apr 2024 11:29:03 +0400 Subject: [PATCH 068/159] fix doc build --- cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs | 2 +- cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 9c39815d2be3..6a46bc79b68d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -339,7 +339,7 @@ pub type NativeAndNonPoolAssets = fungible::UnionOf< AccountId, >; -/// Union fungibles implementation for [`PoolAssets`] and [`NativeAndAssets`]. +/// Union fungibles implementation for [`PoolAssets`] and [`NativeAndNonPoolAssets`]. /// /// NOTE: Should be kept updated to include ALL balances and assets in the runtime. pub type NativeAndAllAssets = fungibles::UnionOf< 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 4b4115783b23..f967ceaa6168 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -319,7 +319,7 @@ pub type NativeAndNonPoolAssets = fungible::UnionOf< AccountId, >; -/// Union fungibles implementation for [`PoolAssets`] and [`NativeAndAssets`]. +/// Union fungibles implementation for [`PoolAssets`] and [`NativeAndNonPoolAssets`]. /// /// NOTE: Should be kept updated to include ALL balances and assets in the runtime. pub type NativeAndAllAssets = fungibles::UnionOf< From 767af862d9d2ccdf30440fced1968e3eb34d421b Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 12 Apr 2024 16:43:40 +0400 Subject: [PATCH 069/159] address comment --- substrate/frame/asset-rewards/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 18e8a852acfb..49bf75c3fd56 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -551,11 +551,12 @@ pub mod pallet { Error::::ExpiryBlockMustBeInTheFuture ); - // Always start by updating the pool rewards. let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + ensure!(pool_info.admin == caller, BadOrigin); + + // Always start by updating the pool rewards. let mut pool_info = Self::update_pool_rewards(pool_info)?; - ensure!(pool_info.admin == caller, BadOrigin); pool_info.expiry_block = new_expiry_block; Pools::::insert(pool_id, pool_info); From 44191335d6bd414b278056aebdb443a76e12d551 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 12 Apr 2024 16:49:17 +0400 Subject: [PATCH 070/159] pure fns --- substrate/frame/asset-rewards/src/lib.rs | 40 +++++++++++++----------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 49bf75c3fd56..1677deaed905 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -53,10 +53,10 @@ //! ## Implementation Notes //! //! Internal logic functions such as `update_pool_and_staker_rewards` where deliberately written -//! without storage interaction. +//! as pure functions without side-effects. //! //! Storage interaction such as reads and writes are instead all performed in the top level -//! pallet Call method, which while slightly more verbose, makes it much easier to understand the +//! pallet Call method, which while slightly more verbose, makes it easier to understand the //! code and reason about how storage reads and writes occur in the pallet. //! //! ## Rewards Algorithm @@ -392,7 +392,7 @@ pub mod pallet { let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; let staker_info = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); let (mut pool_info, mut staker_info) = - Self::update_pool_and_staker_rewards(pool_info, staker_info)?; + Self::update_pool_and_staker_rewards(&pool_info, &staker_info)?; // Try to freeze the staker assets. // TODO: (blocked https://github.com/paritytech/polkadot-sdk/issues/3342) @@ -424,7 +424,7 @@ pub mod pallet { let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; let staker_info = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); let (mut pool_info, mut staker_info) = - Self::update_pool_and_staker_rewards(pool_info, staker_info)?; + Self::update_pool_and_staker_rewards(&pool_info, &staker_info)?; // Check the staker has enough staked tokens. ensure!(staker_info.amount >= amount, Error::::NotEnoughTokens); @@ -462,7 +462,7 @@ pub mod pallet { let staker_info = PoolStakers::::get(pool_id, &staker).ok_or(Error::::NonExistentStaker)?; let (pool_info, mut staker_info) = - Self::update_pool_and_staker_rewards(pool_info, staker_info)?; + Self::update_pool_and_staker_rewards(&pool_info, &staker_info)?; // Transfer unclaimed rewards from the pool to the staker. let pool_account_id = Self::pool_account_id(&pool_id)?; @@ -503,7 +503,7 @@ pub mod pallet { ensure!(caller == pool_info.admin, BadOrigin); // Always start by updating the pool rewards. - let mut pool_info = Self::update_pool_rewards(pool_info)?; + let mut pool_info = Self::update_pool_rewards(&pool_info)?; pool_info.reward_rate_per_block = new_reward_rate_per_block; Pools::::insert(pool_id, pool_info); @@ -555,7 +555,7 @@ pub mod pallet { ensure!(pool_info.admin == caller, BadOrigin); // Always start by updating the pool rewards. - let mut pool_info = Self::update_pool_rewards(pool_info)?; + let mut pool_info = Self::update_pool_rewards(&pool_info)?; pool_info.expiry_block = new_expiry_block; Pools::::insert(pool_id, pool_info); @@ -631,16 +631,18 @@ pub mod pallet { /// /// Returns the updated pool and staker info. /// - /// NOTE: does not modify any storage, that is the responsibility of the caller. + /// NOTE: this is a pure function without any side-effects. Side-effects such as storage + /// modifications are the resopnsibility of the caller. pub fn update_pool_and_staker_rewards( - pool_info: PoolInfoFor, - mut staker_info: PoolStakerInfo, + pool_info: &PoolInfoFor, + staker_info: &PoolStakerInfo, ) -> Result<(PoolInfoFor, PoolStakerInfo), DispatchError> { let pool_info = Self::update_pool_rewards(pool_info)?; - staker_info.rewards = Self::derive_rewards(&pool_info, &staker_info)?; - staker_info.reward_per_token_paid = pool_info.reward_per_token_stored; - return Ok((pool_info, staker_info)); + let mut new_staker_info = staker_info.clone(); + new_staker_info.rewards = Self::derive_rewards(&pool_info, &staker_info)?; + new_staker_info.reward_per_token_paid = pool_info.reward_per_token_stored; + return Ok((pool_info, new_staker_info)); } /// Computes update pool reward state. @@ -649,16 +651,18 @@ pub mod pallet { /// /// Returns the updated pool and staker info. /// - /// NOTE: does not modify any storage, that is the responsibility of the caller. + /// NOTE: this is a pure function without any side-effects. Side-effects such as storage + /// modifications are the resopnsibility of the caller. pub fn update_pool_rewards( - mut pool_info: PoolInfoFor, + pool_info: &PoolInfoFor, ) -> Result, DispatchError> { let reward_per_token = Self::reward_per_token(&pool_info)?; - pool_info.last_update_block = frame_system::Pallet::::block_number(); - pool_info.reward_per_token_stored = reward_per_token; + let mut new_pool_info = pool_info.clone(); + new_pool_info.last_update_block = frame_system::Pallet::::block_number(); + new_pool_info.reward_per_token_stored = reward_per_token; - Ok(pool_info) + Ok(new_pool_info) } /// Derives the current reward per token for this pool. From f903ea2e9ebadb20fbe9c9eb310c4b0769085602 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 12 Apr 2024 16:52:29 +0400 Subject: [PATCH 071/159] is_zero() --- substrate/frame/asset-rewards/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 1677deaed905..61d433a7972e 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -90,7 +90,7 @@ use frame_support::{ }; use scale_info::TypeInfo; use sp_core::Get; -use sp_runtime::DispatchError; +use sp_runtime::{traits::Zero, DispatchError}; use sp_std::boxed::Box; #[cfg(feature = "runtime-benchmarks")] @@ -669,7 +669,7 @@ pub mod pallet { /// /// This is a helper function for `update_pool_rewards` and should not be called directly. fn reward_per_token(pool_info: &PoolInfoFor) -> Result { - if pool_info.total_tokens_staked.eq(&0u32.into()) { + if pool_info.total_tokens_staked.is_zero() { return Ok(pool_info.reward_per_token_stored) } From cd77fb3bb9b99b52fa7cc2168e9c12a314d9c75b Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 12 Apr 2024 16:55:06 +0400 Subject: [PATCH 072/159] update doc --- substrate/frame/asset-rewards/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 61d433a7972e..4b838d1d5865 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -53,7 +53,7 @@ //! ## Implementation Notes //! //! Internal logic functions such as `update_pool_and_staker_rewards` where deliberately written -//! as pure functions without side-effects. +//! without side-effects. //! //! Storage interaction such as reads and writes are instead all performed in the top level //! pallet Call method, which while slightly more verbose, makes it easier to understand the @@ -631,8 +631,8 @@ pub mod pallet { /// /// Returns the updated pool and staker info. /// - /// NOTE: this is a pure function without any side-effects. Side-effects such as storage - /// modifications are the resopnsibility of the caller. + /// NOTE: this function has no side-effects. Side-effects such as storage modifications are + /// the resopnsibility of the caller. pub fn update_pool_and_staker_rewards( pool_info: &PoolInfoFor, staker_info: &PoolStakerInfo, @@ -651,8 +651,8 @@ pub mod pallet { /// /// Returns the updated pool and staker info. /// - /// NOTE: this is a pure function without any side-effects. Side-effects such as storage - /// modifications are the resopnsibility of the caller. + /// NOTE: this function has no side-effects. Side-effects such as storage modifications are + /// the resopnsibility of the caller. pub fn update_pool_rewards( pool_info: &PoolInfoFor, ) -> Result, DispatchError> { From 67b23fade36565b0497af9555b4499f5a6d9f8a5 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Mon, 15 Apr 2024 10:04:31 +0400 Subject: [PATCH 073/159] finish merging location refactor --- .../runtimes/assets/asset-hub-rococo/src/lib.rs | 5 ++--- .../assets/asset-hub-rococo/src/xcm_config.rs | 2 ++ .../runtimes/assets/asset-hub-westend/src/lib.rs | 5 ++--- .../assets/asset-hub-westend/src/xcm_config.rs | 2 ++ cumulus/parachains/runtimes/assets/common/src/lib.rs | 11 ++--------- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 942f8cf8639c..8df40f677f68 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -31,8 +31,7 @@ use assets_common::{ foreign_creators::ForeignCreators, local_and_foreign_assets::{LocalFromLeft, TargetFromLeft}, matching::{FromNetwork, FromSiblingParachain}, - AssetIdForPoolAssets, AssetIdForPoolAssetsConvertV3Location, - AssetIdForTrustBackedAssetsConvert, + AssetIdForPoolAssets, AssetIdForPoolAssetsConvert, AssetIdForTrustBackedAssetsConvert, }; use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; use cumulus_primitives_core::AggregateMessageOrigin; @@ -346,7 +345,7 @@ pub type NativeAndAllAssets = fungibles::UnionOf< PoolAssets, NativeAndNonPoolAssets, LocalFromLeft< - AssetIdForPoolAssetsConvertV3Location, + AssetIdForPoolAssetsConvert, AssetIdForPoolAssets, xcm::v3::Location, >, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index c464fec4edd6..4e525261931a 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -76,6 +76,8 @@ parameter_types! { pub TrustBackedAssetsPalletIndex: u8 = ::index() as u8; pub TrustBackedAssetsPalletLocationV3: xcm::v3::Location = xcm::v3::Junction::PalletInstance(::index() as u8).into(); + pub PoolAssetsPalletLocationV3: xcm::v3::Location = + xcm::v3::Junction::PalletInstance(::index() as u8).into(); pub ForeignAssetsPalletLocation: Location = PalletInstance(::index() as u8).into(); pub PoolAssetsPalletLocation: Location = 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 35b73d89dcde..b6b4f7eab3d1 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -29,8 +29,7 @@ pub mod xcm_config; use assets_common::{ local_and_foreign_assets::{LocalFromLeft, TargetFromLeft}, - AssetIdForPoolAssets, AssetIdForPoolAssetsConvertV3Location, - AssetIdForTrustBackedAssetsConvert, + AssetIdForPoolAssets, AssetIdForPoolAssetsConvert, AssetIdForTrustBackedAssetsConvert, }; use codec::{Decode, Encode, MaxEncodedLen}; use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; @@ -326,7 +325,7 @@ pub type NativeAndAllAssets = fungibles::UnionOf< PoolAssets, NativeAndNonPoolAssets, LocalFromLeft< - AssetIdForPoolAssetsConvertV3Location, + AssetIdForPoolAssetsConvert, AssetIdForPoolAssets, xcm::v3::Location, >, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index 9ba07ccdc038..7105925fc9f7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -73,6 +73,8 @@ parameter_types! { pub TrustBackedAssetsPalletIndex: u8 = ::index() as u8; pub TrustBackedAssetsPalletLocationV3: xcm::v3::Location = xcm::v3::Junction::PalletInstance(::index() as u8).into(); + pub PoolAssetsPalletLocationV3: xcm::v3::Location = + xcm::v3::Junction::PalletInstance(::index() as u8).into(); pub ForeignAssetsPalletLocation: Location = PalletInstance(::index() as u8).into(); pub PoolAssetsPalletLocation: Location = diff --git a/cumulus/parachains/runtimes/assets/common/src/lib.rs b/cumulus/parachains/runtimes/assets/common/src/lib.rs index 1b99549619ad..24c9a8639814 100644 --- a/cumulus/parachains/runtimes/assets/common/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/common/src/lib.rs @@ -119,17 +119,10 @@ pub type ForeignAssetsConvertedConcreteId< >; pub type AssetIdForPoolAssets = u32; -/// `Location` vs `AssetIdForPoolAssets` converter for `PoolAssets` with explicit `v3 Location`. -pub type AssetIdForPoolAssetsConvertV3Location = AsPrefixedGeneralIndex< - PoolAssetsPalletLocation, - AssetIdForPoolAssets, - JustTry, - xcm::v3::Location, ->; /// `Location` vs `AssetIdForPoolAssets` converter for `PoolAssets`. -pub type AssetIdForPoolAssetsConvert = - AsPrefixedGeneralIndex; +pub type AssetIdForPoolAssetsConvert = + AsPrefixedGeneralIndex; /// [`MatchedConvertedConcreteId`] converter dedicated for `PoolAssets` pub type PoolAssetsConvertedConcreteId = MatchedConvertedConcreteId< From 9851b31960f8e33f686e8a056782c0fe8865d260 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 16 Apr 2024 00:42:40 +1000 Subject: [PATCH 074/159] Update substrate/frame/asset-rewards/src/lib.rs Co-authored-by: Oliver Tale-Yazdi --- substrate/frame/asset-rewards/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 4b838d1d5865..344168cce527 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -128,7 +128,7 @@ pub struct PoolStakerInfo { reward_per_token_paid: Balance, } -/// The state and configuration an incentive pool. +/// The state and configuration of an incentive pool. #[derive(Debug, Clone, Decode, Encode, Default, PartialEq, Eq, MaxEncodedLen, TypeInfo)] pub struct PoolInfo { /// The asset staked in this pool. From 7e05c06118fd4b3a62b4642685acba3b4a2e7a6e Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 16 Apr 2024 01:06:33 +1000 Subject: [PATCH 075/159] Update substrate/frame/asset-rewards/src/lib.rs Co-authored-by: Oliver Tale-Yazdi --- substrate/frame/asset-rewards/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 344168cce527..a95136ed91de 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -217,7 +217,7 @@ pub mod pallet { _, Blake2_128Concat, PoolId, - PoolInfo>, + PoolInfoFor, >; /// Stores the [`PoolId`] to use for the next pool. From a1620529dde7787eeed9e11b401266296285b130 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 16 Apr 2024 01:54:18 +1000 Subject: [PATCH 076/159] Update substrate/frame/asset-rewards/src/lib.rs Co-authored-by: Oliver Tale-Yazdi --- substrate/frame/asset-rewards/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index a95136ed91de..0ef3351a2b73 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -632,7 +632,7 @@ pub mod pallet { /// Returns the updated pool and staker info. /// /// NOTE: this function has no side-effects. Side-effects such as storage modifications are - /// the resopnsibility of the caller. + /// the responsibility of the caller. pub fn update_pool_and_staker_rewards( pool_info: &PoolInfoFor, staker_info: &PoolStakerInfo, From be25a9e9cc0ab1acfeea7f73350158b8eb12385c Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 16 Apr 2024 01:54:33 +1000 Subject: [PATCH 077/159] Update substrate/frame/asset-rewards/src/lib.rs Co-authored-by: Oliver Tale-Yazdi --- substrate/frame/asset-rewards/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 0ef3351a2b73..ac1df2037c2f 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -652,7 +652,7 @@ pub mod pallet { /// Returns the updated pool and staker info. /// /// NOTE: this function has no side-effects. Side-effects such as storage modifications are - /// the resopnsibility of the caller. + /// the responsibility of the caller. pub fn update_pool_rewards( pool_info: &PoolInfoFor, ) -> Result, DispatchError> { From 9c9da9aeefba3ffe144a6cfed65ae49ed578fa34 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Mon, 15 Apr 2024 19:59:21 +0400 Subject: [PATCH 078/159] update comment --- substrate/frame/asset-rewards/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 4b838d1d5865..8f57c30ac600 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -315,9 +315,6 @@ pub mod pallet { } /// Pallet's callable functions. - /// - /// Allows optionally specifying an admin account for the pool. By default, the origin is made - /// admin. #[pallet::call(weight(::WeightInfo))] impl Pallet { /// Create a new reward pool. From 446ae58973b058b448d1dbd867d7c41a6bef8a43 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 16 Apr 2024 09:15:47 +0400 Subject: [PATCH 079/159] wip emulated test --- Cargo.lock | 1 + .../emulated/common/src/lib.rs | 1 + .../tests/assets/asset-hub-rococo/Cargo.toml | 1 + .../assets/asset-hub-rococo/src/tests/mod.rs | 1 + .../src/tests/treasury_asset_reward_pool.rs | 92 +++++++++++++++++++ 5 files changed, 96 insertions(+) create mode 100644 cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs diff --git a/Cargo.lock b/Cargo.lock index e9022ed1d8d9..5e7959cf918b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -823,6 +823,7 @@ dependencies = [ "emulated-integration-tests-common", "frame-support", "pallet-asset-conversion", + "pallet-asset-rewards", "pallet-assets", "pallet-balances", "pallet-message-queue", diff --git a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs index cbde0642f1a2..87cb8cba13b8 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs @@ -57,6 +57,7 @@ pub const RESERVABLE_ASSET_ID: u32 = 1; pub const TELEPORTABLE_ASSET_ID: u32 = 2; pub const PENPAL_ID: u32 = 2000; +pub const ASSET_HUB_ROCOCO_ID: u32 = 1000; pub const ASSETS_PALLET_ID: u8 = 50; parameter_types! { diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml index c5a672234a0d..64fee0241a4d 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml @@ -20,6 +20,7 @@ frame-support = { path = "../../../../../../../substrate/frame/support", default pallet-balances = { path = "../../../../../../../substrate/frame/balances", default-features = false } pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-features = false } pallet-asset-conversion = { path = "../../../../../../../substrate/frame/asset-conversion", default-features = false } +pallet-asset-rewards = { path = "../../../../../../../substrate/frame/asset-rewards", default-features = false } pallet-message-queue = { path = "../../../../../../../substrate/frame/message-queue", default-features = false } # Polkadot diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs index 2402989225af..dfe0a7561d50 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs @@ -19,3 +19,4 @@ mod send; mod set_xcm_versions; mod swap; mod teleport; +mod treasury_asset_reward_pool; diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs new file mode 100644 index 000000000000..280f02e93ace --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs @@ -0,0 +1,92 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::imports::*; +use asset_hub_rococo_runtime::{ + xcm_config::{GovernanceLocation, RelayTreasuryLocation}, + TreasurerBodyId, +}; +use codec::Encode; +use emulated_integration_tests_common::ASSET_HUB_ROCOCO_ID; +use frame_support::{assert_ok, sp_runtime::traits::Dispatchable}; +use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; + +#[test] +fn treasury_creates_asset_reward_pool() { + AssetHubRococo::execute_with(|| { + type AssetHubRococoRuntimeEvent = ::RuntimeEvent; + type AssetHubRococoRuntimeCall = ::RuntimeCall; + type AssetHubRococoRuntimeOrigin = ::RuntimeOrigin; + type AssetHubRococoRuntime = ::Runtime; + type RococoRuntimeCall = ::RuntimeCall; + type RococoRuntime = ::Runtime; + type RococoRuntimeOrigin = ::RuntimeOrigin; + + let staked_asset_id = bx!(xcm::v3::Junction::PalletInstance(1).into()); + let reward_asset_id = bx!(xcm::v3::Junction::PalletInstance(2).into()); + let reward_rate_per_block = 1_000_000_000; + let expiry_block = 1_000_000_000; + let admin = None; + + let create_pool_call = + RococoRuntimeCall::XcmPallet(pallet_xcm::Call::::send { + dest: bx!(VersionedLocation::V4( + xcm::v4::Junction::Parachain(ASSET_HUB_ROCOCO_ID).into() + )), + message: bx!(VersionedXcm::V4(Xcm(vec![ + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, + Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: Weight::from_parts(5_000_000_000, 500_000), + call: AssetHubRococoRuntimeCall::AssetRewards( + pallet_asset_rewards::Call::::create_pool { + staked_asset_id, + reward_asset_id, + reward_rate_per_block, + expiry_block, + admin + } + ) + .encode() + .into(), + } + ]))), + }); + + let treasury_origin: RococoRuntimeOrigin = + rococo_runtime::governance::pallet_custom_origins::Origin::Treasurer.into(); + + assert_ok!(create_pool_call.dispatch(treasury_origin)); + + // assert_expected_events!( + // CollectivesPolkadot, + // vec![ + // RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {}, + // ] + // ); + // }); + // + // Polkadot::execute_with(|| { + // type RuntimeEvent = ::RuntimeEvent; + // + // assert_expected_events!( + // Polkadot, + // vec![ + // RuntimeEvent::Whitelist(pallet_whitelist::Event::CallWhitelisted { .. }) => {}, + // RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) + // => {}, ] + // ); + }); +} From bf04e6dbedfaad793c8023a6f89fbd6cb546d392 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 16 Apr 2024 18:56:55 +0400 Subject: [PATCH 080/159] wip emulated test --- .../src/tests/treasury_asset_reward_pool.rs | 41 +++++++------------ 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs index 280f02e93ace..309f69428e56 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs @@ -14,24 +14,18 @@ // limitations under the License. use crate::imports::*; -use asset_hub_rococo_runtime::{ - xcm_config::{GovernanceLocation, RelayTreasuryLocation}, - TreasurerBodyId, -}; use codec::Encode; use emulated_integration_tests_common::ASSET_HUB_ROCOCO_ID; use frame_support::{assert_ok, sp_runtime::traits::Dispatchable}; -use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; #[test] fn treasury_creates_asset_reward_pool() { - AssetHubRococo::execute_with(|| { - type AssetHubRococoRuntimeEvent = ::RuntimeEvent; + Rococo::execute_with(|| { type AssetHubRococoRuntimeCall = ::RuntimeCall; - type AssetHubRococoRuntimeOrigin = ::RuntimeOrigin; type AssetHubRococoRuntime = ::Runtime; type RococoRuntimeCall = ::RuntimeCall; type RococoRuntime = ::Runtime; + type RococoRuntimeEvent = ::RuntimeEvent; type RococoRuntimeOrigin = ::RuntimeOrigin; let staked_asset_id = bx!(xcm::v3::Junction::PalletInstance(1).into()); @@ -67,26 +61,19 @@ fn treasury_creates_asset_reward_pool() { let treasury_origin: RococoRuntimeOrigin = rococo_runtime::governance::pallet_custom_origins::Origin::Treasurer.into(); + // TODO: Figure out how to enable treasury origin + // assert_ok!(create_pool_call.dispatch(treasury_origin)); + assert_ok!(create_pool_call.dispatch(RococoRuntimeOrigin::root())); - assert_ok!(create_pool_call.dispatch(treasury_origin)); + assert_expected_events!( + Rococo, + vec![ + RococoRuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); - // assert_expected_events!( - // CollectivesPolkadot, - // vec![ - // RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {}, - // ] - // ); - // }); - // - // Polkadot::execute_with(|| { - // type RuntimeEvent = ::RuntimeEvent; - // - // assert_expected_events!( - // Polkadot, - // vec![ - // RuntimeEvent::Whitelist(pallet_whitelist::Event::CallWhitelisted { .. }) => {}, - // RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) - // => {}, ] - // ); + AssetHubRococo::execute_with(|| { + // TODO: Check that the pool was created }); } From 3a851c8f72e8073e61c60628dcfb5ee97604c2ee Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 10:57:21 +0400 Subject: [PATCH 081/159] emulated tests --- Cargo.lock | 1 + .../emulated/common/src/lib.rs | 1 + .../src/tests/treasury_asset_reward_pool.rs | 24 +++-- .../tests/assets/asset-hub-westend/Cargo.toml | 1 + .../assets/asset-hub-westend/src/tests/mod.rs | 1 + .../src/tests/treasury_asset_reward_pool.rs | 91 +++++++++++++++++++ .../assets/asset-hub-rococo/src/xcm_config.rs | 9 +- .../asset-hub-westend/src/xcm_config.rs | 9 +- polkadot/runtime/rococo/src/xcm_config.rs | 17 +++- polkadot/runtime/westend/src/xcm_config.rs | 2 +- 10 files changed, 137 insertions(+), 19 deletions(-) create mode 100644 cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs diff --git a/Cargo.lock b/Cargo.lock index db87de219ef9..32dee11171fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -947,6 +947,7 @@ dependencies = [ "emulated-integration-tests-common", "frame-support", "pallet-asset-conversion", + "pallet-asset-rewards", "pallet-assets", "pallet-balances", "pallet-message-queue", diff --git a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs index 87cb8cba13b8..1bde52f2e75a 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs @@ -58,6 +58,7 @@ pub const TELEPORTABLE_ASSET_ID: u32 = 2; pub const PENPAL_ID: u32 = 2000; pub const ASSET_HUB_ROCOCO_ID: u32 = 1000; +pub const ASSET_HUB_WESTEND_ID: u32 = 1000; pub const ASSETS_PALLET_ID: u8 = 50; parameter_types! { diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs index 309f69428e56..4dd23dbca78e 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs @@ -14,6 +14,7 @@ // limitations under the License. use crate::imports::*; +use asset_hub_rococo_runtime::xcm_config::TokenLocationV3; use codec::Encode; use emulated_integration_tests_common::ASSET_HUB_ROCOCO_ID; use frame_support::{assert_ok, sp_runtime::traits::Dispatchable}; @@ -28,8 +29,9 @@ fn treasury_creates_asset_reward_pool() { type RococoRuntimeEvent = ::RuntimeEvent; type RococoRuntimeOrigin = ::RuntimeOrigin; - let staked_asset_id = bx!(xcm::v3::Junction::PalletInstance(1).into()); - let reward_asset_id = bx!(xcm::v3::Junction::PalletInstance(2).into()); + let staked_asset_id = bx!(TokenLocationV3::get()); + let reward_asset_id = bx!(TokenLocationV3::get()); + let reward_rate_per_block = 1_000_000_000; let expiry_block = 1_000_000_000; let admin = None; @@ -61,9 +63,7 @@ fn treasury_creates_asset_reward_pool() { let treasury_origin: RococoRuntimeOrigin = rococo_runtime::governance::pallet_custom_origins::Origin::Treasurer.into(); - // TODO: Figure out how to enable treasury origin - // assert_ok!(create_pool_call.dispatch(treasury_origin)); - assert_ok!(create_pool_call.dispatch(RococoRuntimeOrigin::root())); + assert_ok!(create_pool_call.dispatch(treasury_origin)); assert_expected_events!( Rococo, @@ -74,6 +74,18 @@ fn treasury_creates_asset_reward_pool() { }); AssetHubRococo::execute_with(|| { - // TODO: Check that the pool was created + type AssetHubRococoRuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + AssetHubRococo, + vec![ + AssetHubRococoRuntimeEvent::AssetRewards( + pallet_asset_rewards::Event::PoolCreated { + .. + } + ) => { + }, + + ] + ); }); } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml index 00f4308324a9..4c089a472641 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml @@ -20,6 +20,7 @@ frame-support = { path = "../../../../../../../substrate/frame/support", default pallet-balances = { path = "../../../../../../../substrate/frame/balances", default-features = false } pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-features = false } pallet-asset-conversion = { path = "../../../../../../../substrate/frame/asset-conversion", default-features = false } +pallet-asset-rewards = { path = "../../../../../../../substrate/frame/asset-rewards", default-features = false } pallet-treasury = { path = "../../../../../../../substrate/frame/treasury", default-features = false } pallet-message-queue = { path = "../../../../../../../substrate/frame/message-queue", default-features = false } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs index e463e21e9e52..9c427d64e795 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs @@ -21,3 +21,4 @@ mod set_xcm_versions; mod swap; mod teleport; mod treasury; +mod treasury_asset_reward_pool; diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs new file mode 100644 index 000000000000..9e9166da1872 --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs @@ -0,0 +1,91 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::imports::*; +use asset_hub_westend_runtime::xcm_config::WestendLocationV3; +use codec::Encode; +use emulated_integration_tests_common::ASSET_HUB_WESTEND_ID; +use frame_support::{assert_ok, sp_runtime::traits::Dispatchable}; + +#[test] +fn treasury_creates_asset_reward_pool() { + Westend::execute_with(|| { + type AssetHubWestendRuntimeCall = ::RuntimeCall; + type AssetHubWestendRuntime = ::Runtime; + type WestendRuntimeCall = ::RuntimeCall; + type WestendRuntime = ::Runtime; + type WestendRuntimeEvent = ::RuntimeEvent; + type WestendRuntimeOrigin = ::RuntimeOrigin; + + let staked_asset_id = bx!(WestendLocationV3::get()); + let reward_asset_id = bx!(WestendLocationV3::get()); + + let reward_rate_per_block = 1_000_000_000; + let expiry_block = 1_000_000_000; + let admin = None; + + let create_pool_call = + WestendRuntimeCall::XcmPallet(pallet_xcm::Call::::send { + dest: bx!(VersionedLocation::V4( + xcm::v4::Junction::Parachain(ASSET_HUB_WESTEND_ID).into() + )), + message: bx!(VersionedXcm::V4(Xcm(vec![ + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, + Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: Weight::from_parts(5_000_000_000, 500_000), + call: AssetHubWestendRuntimeCall::AssetRewards( + pallet_asset_rewards::Call::::create_pool { + staked_asset_id, + reward_asset_id, + reward_rate_per_block, + expiry_block, + admin + } + ) + .encode() + .into(), + } + ]))), + }); + + let treasury_origin: WestendRuntimeOrigin = + westend_runtime::governance::pallet_custom_origins::Origin::Treasurer.into(); + assert_ok!(create_pool_call.dispatch(treasury_origin)); + + assert_expected_events!( + Westend, + vec![ + WestendRuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); + + AssetHubWestend::execute_with(|| { + type AssetHubWestendRuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + AssetHubWestend, + vec![ + AssetHubWestendRuntimeEvent::AssetRewards( + pallet_asset_rewards::Event::PoolCreated { + .. + } + ) => { + }, + + ] + ); + }); +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 4e525261931a..0442ee2db883 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -296,10 +296,11 @@ impl Contains for SafeCallFilter { matches!( call, - RuntimeCall::PolkadotXcm( - pallet_xcm::Call::force_xcm_version { .. } | - pallet_xcm::Call::force_default_xcm_version { .. } - ) | RuntimeCall::System( + RuntimeCall::AssetRewards(pallet_asset_rewards::Call::create_pool { .. }) | + RuntimeCall::PolkadotXcm( + pallet_xcm::Call::force_xcm_version { .. } | + pallet_xcm::Call::force_default_xcm_version { .. } + ) | RuntimeCall::System( frame_system::Call::set_heap_pages { .. } | frame_system::Call::set_code { .. } | frame_system::Call::set_code_without_checks { .. } | diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index 7105925fc9f7..d9d66cc2bf95 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -308,10 +308,11 @@ impl Contains for SafeCallFilter { matches!( call, - RuntimeCall::PolkadotXcm( - pallet_xcm::Call::force_xcm_version { .. } | - pallet_xcm::Call::force_default_xcm_version { .. } - ) | RuntimeCall::System( + RuntimeCall::AssetRewards(pallet_asset_rewards::Call::create_pool { .. }) | + RuntimeCall::PolkadotXcm( + pallet_xcm::Call::force_xcm_version { .. } | + pallet_xcm::Call::force_default_xcm_version { .. } + ) | RuntimeCall::System( frame_system::Call::set_heap_pages { .. } | frame_system::Call::set_code { .. } | frame_system::Call::set_code_without_checks { .. } | diff --git a/polkadot/runtime/rococo/src/xcm_config.rs b/polkadot/runtime/rococo/src/xcm_config.rs index c7063bd7ad61..dd8660d77509 100644 --- a/polkadot/runtime/rococo/src/xcm_config.rs +++ b/polkadot/runtime/rococo/src/xcm_config.rs @@ -18,7 +18,8 @@ use super::{ parachains_origin, AccountId, AllPalletsWithSystem, Balances, Dmp, Fellows, ParaId, Runtime, - RuntimeCall, RuntimeEvent, RuntimeOrigin, TransactionByteFee, Treasury, WeightToFee, XcmPallet, + RuntimeCall, RuntimeEvent, RuntimeOrigin, TransactionByteFee, Treasurer, Treasury, WeightToFee, + XcmPallet, }; use crate::governance::StakingAdmin; @@ -227,11 +228,14 @@ impl xcm_executor::Config for XcmConfig { } parameter_types! { + /// Collective pluralistic body. pub const CollectiveBodyId: BodyId = BodyId::Unit; - // StakingAdmin pluralistic body. + /// StakingAdmin pluralistic body. pub const StakingAdminBodyId: BodyId = BodyId::Defense; - // Fellows pluralistic body. + /// Fellows pluralistic body. pub const FellowsBodyId: BodyId = BodyId::Technical; + /// Treasury pluralistic body. + pub const TreasuryBodyId: BodyId = BodyId::Treasury; } /// Type to convert an `Origin` type value into a `Location` value which represents an interior @@ -248,6 +252,9 @@ pub type StakingAdminToPlurality = /// Type to convert the Fellows origin to a Plurality `Location` value. pub type FellowsToPlurality = OriginToPluralityVoice; +/// Type to convert the Treasury origin to a Plurality `Location` value. +pub type TreasurerToPlurality = OriginToPluralityVoice; + /// Type to convert a pallet `Origin` type value into a `Location` value which represents an /// interior location of this chain for a destination chain. pub type LocalPalletOriginToLocation = ( @@ -255,13 +262,15 @@ pub type LocalPalletOriginToLocation = ( StakingAdminToPlurality, // Fellows origin to be used in XCM as a corresponding Plurality `Location` value. FellowsToPlurality, + // Treasurer origin to be used in XCM as a corresponding Plurality `Location` value. + TreasurerToPlurality, ); impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; // Note that this configuration of `SendXcmOrigin` is different from the one present in // production. - type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; type XcmRouter = XcmRouter; // Anyone can execute XCM messages locally. type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index f661c4b0e4f4..a06df2a19683 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -274,7 +274,7 @@ impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; // Note that this configuration of `SendXcmOrigin` is different from the one present in // production. - type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; type XcmRouter = XcmRouter; // Anyone can execute XCM messages locally. type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; From a4eb51f7843198be944b74151181e27856c7f624 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 10:58:14 +0400 Subject: [PATCH 082/159] use poolinfofor --- substrate/frame/asset-rewards/src/lib.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index d3483587c1a8..9053d540681d 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -213,12 +213,7 @@ pub mod pallet { /// State and configuraiton of each staking pool. #[pallet::storage] - pub type Pools = StorageMap< - _, - Blake2_128Concat, - PoolId, - PoolInfoFor, - >; + pub type Pools = StorageMap<_, Blake2_128Concat, PoolId, PoolInfoFor>; /// Stores the [`PoolId`] to use for the next pool. /// From 1ecc7e2e11d155a73296c6dda248d607bffc3dd7 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 11:18:20 +0400 Subject: [PATCH 083/159] update comment --- substrate/frame/asset-rewards/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 9053d540681d..56564a540350 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -43,7 +43,7 @@ //! //! ## Permissioning //! -//! Currently, pool creation and management is permissioned and restricted to a configured Origin. +//! Currently, pool creation and management restricted to a configured Origin. //! //! Future iterations of this pallet may allow permissionless creation and management of pools. //! From af92541eeb5addb0a90c9cc82dbf00bf1d069fd6 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 11:24:43 +0400 Subject: [PATCH 084/159] improve call docs --- substrate/frame/asset-rewards/src/lib.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 56564a540350..1b7e9c2f0198 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -313,6 +313,8 @@ pub mod pallet { #[pallet::call(weight(::WeightInfo))] impl Pallet { /// Create a new reward pool. + /// + /// If an explicity admin is not specified, it defaults to the caller. #[pallet::call_index(0)] pub fn create_pool( origin: OriginFor, @@ -376,6 +378,8 @@ pub mod pallet { } /// Stake tokens in a pool. + /// + /// A freeze is placed on the staked tokens. #[pallet::call_index(1)] pub fn stake(origin: OriginFor, pool_id: PoolId, amount: T::Balance) -> DispatchResult { let caller = ensure_signed(origin)?; @@ -404,6 +408,8 @@ pub mod pallet { } /// Unstake tokens from a pool. + /// + /// Removes the freeze on the staked tokens. #[pallet::call_index(2)] pub fn unstake( origin: OriginFor, @@ -439,6 +445,9 @@ pub mod pallet { } /// Harvest unclaimed pool rewards for a staker. + /// + /// Anyone may harvest rewards on behalf of a staker. If an explicit staker is not provided, + /// the caller is assumed to be the staker. #[pallet::call_index(3)] pub fn harvest_rewards( origin: OriginFor, From 905e102f50909cb96df6db7d1517174a25ddb151 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 11:25:47 +0400 Subject: [PATCH 085/159] update call comment --- substrate/frame/asset-rewards/src/lib.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 1b7e9c2f0198..d3f084d0cfdc 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -377,7 +377,7 @@ pub mod pallet { Ok(()) } - /// Stake tokens in a pool. + /// Stake additional tokens in a pool. /// /// A freeze is placed on the staked tokens. #[pallet::call_index(1)] @@ -491,6 +491,8 @@ pub mod pallet { } /// Modify a pool reward rate. + /// + /// Only the pool admin may perform this operation. #[pallet::call_index(4)] pub fn set_pool_reward_rate_per_block( origin: OriginFor, @@ -518,6 +520,8 @@ pub mod pallet { } /// Modify a pool admin. + /// + /// Only the pool admin may perform this operation. #[pallet::call_index(5)] pub fn set_pool_admin( origin: OriginFor, @@ -538,6 +542,8 @@ pub mod pallet { } /// Modify a expiry block. + /// + /// Only the pool admin may perform this operation. #[pallet::call_index(6)] pub fn set_pool_expiry_block( origin: OriginFor, @@ -591,6 +597,8 @@ pub mod pallet { } /// Permissioned method to withdraw reward tokens from a pool. + /// + /// Only the pool admin may perform this operation. #[pallet::call_index(8)] pub fn withdraw_reward_tokens( origin: OriginFor, From ed9e0dc8959d12078691fe93a603958cb064e680 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 13:12:00 +0400 Subject: [PATCH 086/159] simplify core logic --- substrate/frame/asset-rewards/src/lib.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index d3f084d0cfdc..423734757914 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -506,7 +506,8 @@ pub mod pallet { ensure!(caller == pool_info.admin, BadOrigin); // Always start by updating the pool rewards. - let mut pool_info = Self::update_pool_rewards(&pool_info)?; + let rewards_per_token = Self::reward_per_token(&pool_info)?; + let mut pool_info = Self::update_pool_rewards(&pool_info, rewards_per_token)?; pool_info.reward_rate_per_block = new_reward_rate_per_block; Pools::::insert(pool_id, pool_info); @@ -562,7 +563,8 @@ pub mod pallet { ensure!(pool_info.admin == caller, BadOrigin); // Always start by updating the pool rewards. - let mut pool_info = Self::update_pool_rewards(&pool_info)?; + let reward_per_token = Self::reward_per_token(&pool_info)?; + let mut pool_info = Self::update_pool_rewards(&pool_info, reward_per_token)?; pool_info.expiry_block = new_expiry_block; Pools::::insert(pool_id, pool_info); @@ -646,10 +648,11 @@ pub mod pallet { pool_info: &PoolInfoFor, staker_info: &PoolStakerInfo, ) -> Result<(PoolInfoFor, PoolStakerInfo), DispatchError> { - let pool_info = Self::update_pool_rewards(pool_info)?; + let reward_per_token = Self::reward_per_token(&pool_info)?; + let pool_info = Self::update_pool_rewards(pool_info, reward_per_token.clone())?; let mut new_staker_info = staker_info.clone(); - new_staker_info.rewards = Self::derive_rewards(&pool_info, &staker_info)?; + new_staker_info.rewards = Self::derive_rewards(&staker_info, &reward_per_token)?; new_staker_info.reward_per_token_paid = pool_info.reward_per_token_stored; return Ok((pool_info, new_staker_info)); } @@ -664,9 +667,8 @@ pub mod pallet { /// the responsibility of the caller. pub fn update_pool_rewards( pool_info: &PoolInfoFor, + reward_per_token: T::Balance, ) -> Result, DispatchError> { - let reward_per_token = Self::reward_per_token(&pool_info)?; - let mut new_pool_info = pool_info.clone(); new_pool_info.last_update_block = frame_system::Pallet::::block_number(); new_pool_info.reward_per_token_stored = reward_per_token; @@ -704,11 +706,9 @@ pub mod pallet { /// /// This is a helper function for `update_pool_rewards` and should not be called directly. fn derive_rewards( - pool_info: &PoolInfoFor, staker_info: &PoolStakerInfo, + reward_per_token: &T::Balance, ) -> Result { - let reward_per_token = Self::reward_per_token(&pool_info)?; - Ok(staker_info .amount .saturating_mul(reward_per_token.saturating_sub(staker_info.reward_per_token_paid)) From c3434eb13fd9092985f4b31b9b9fee7b7b726172 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 13:37:44 +0400 Subject: [PATCH 087/159] reduce scaling factor --- substrate/frame/asset-rewards/src/lib.rs | 2 +- substrate/frame/asset-rewards/src/tests.rs | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 423734757914..0e70166a015a 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -107,7 +107,7 @@ pub use weights::WeightInfo; pub type PoolId = u32; /// Multiplier to maintain precision when calculating rewards. -pub(crate) const PRECISION_SCALING_FACTOR: u32 = u32::MAX; +pub(crate) const PRECISION_SCALING_FACTOR: u16 = 4096; /// Convenience alias for `PoolInfo`. pub type PoolInfoFor = PoolInfo< diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 27ff29833912..417d4185e57e 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -921,7 +921,7 @@ mod set_pool_reward_rate_per_block { // Check that rewards are calculated correctly with the updated rate assert_hypothetically_earned( staker, - 10 * 100 + 10 * new_reward_rate - 1, // -1 due to rounding + 10 * 100 + 10 * new_reward_rate, pool_id, NativeOrWithId::::Native, ); @@ -1227,8 +1227,8 @@ fn integration() { // - Staker 2 is earning 33.33 tokens per block. // Check that Staker 1 has earned 350 tokens and Staker 2 has earned 150 tokens. - assert_hypothetically_earned(staker1, 349, pool_id, reward_asset_id.clone()); - assert_hypothetically_earned(staker2, 149, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker1, 350, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 150, pool_id, reward_asset_id.clone()); // Block 22: Staker 1 unstakes 100 tokens. System::set_block_number(22); @@ -1237,7 +1237,7 @@ fn integration() { // - Staker 2 has earned 483 (150 + 33.33 * 10) tokens. // - Staker 1 is earning 50 tokens per block. // - Staker 2 is earning 50 tokens per block. - assert_hypothetically_earned(staker1, 1015, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker1, 1016, pool_id, reward_asset_id.clone()); assert_hypothetically_earned(staker2, 483, pool_id, reward_asset_id.clone()); // Block 23: Staker 1 unstakes 100 tokens. @@ -1247,7 +1247,7 @@ fn integration() { // - Staker 2 has earned 533 (483 + 50) tokens. // - Staker 1 is earning 0 tokens per block. // - Staker 2 is earning 100 tokens per block. - assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker1, 1066, pool_id, reward_asset_id.clone()); assert_hypothetically_earned(staker2, 533, pool_id, reward_asset_id.clone()); // Block 50: Stakers should only have earned 2 blocks worth of tokens (expiry is 25). @@ -1256,7 +1256,7 @@ fn integration() { // - Staker 2 has earned 733 (533 + 2 * 100) tokens. // - Staker 1 is earning 0 tokens per block. // - Staker 2 is earning 0 tokens per block. - assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker1, 1066, pool_id, reward_asset_id.clone()); assert_hypothetically_earned(staker2, 733, pool_id, reward_asset_id.clone()); // Block 51: Extend the pool expiry block to 60. @@ -1268,7 +1268,7 @@ fn integration() { pool_id, 60u64 )); - assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker1, 1066, pool_id, reward_asset_id.clone()); assert_hypothetically_earned(staker2, 733, pool_id, reward_asset_id.clone()); // Block 53: Check rewards are resumed. @@ -1276,7 +1276,7 @@ fn integration() { // - Staker 2 has earned 933 (733 + 2 * 100) tokens. // - Staker 2 is earning 100 tokens per block. System::set_block_number(53); - assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker1, 1066, pool_id, reward_asset_id.clone()); assert_hypothetically_earned(staker2, 933, pool_id, reward_asset_id.clone()); // Block 55: Halve the block reward. @@ -1289,7 +1289,7 @@ fn integration() { pool_id, 50 )); - assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker1, 1066, pool_id, reward_asset_id.clone()); assert_hypothetically_earned(staker2, 1133, pool_id, reward_asset_id.clone()); // Block 57: Staker2 harvests their rewards. @@ -1308,8 +1308,8 @@ fn integration() { // - Staker 1 has earned 1065 tokens. // - Staker 2 has earned 149 (3 * 50) tokens. System::set_block_number(60); - assert_hypothetically_earned(staker1, 1064, pool_id, reward_asset_id.clone()); - assert_hypothetically_earned(staker2, 149, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker1, 1066, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 150, pool_id, reward_asset_id.clone()); // Finally, check events. assert_eq!( From 700ec32cc69ac56677e72e1d7cc5d6a107a2ff83 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 13:40:31 +0400 Subject: [PATCH 088/159] add disambiguation comment --- substrate/frame/asset-rewards/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 0e70166a015a..472bf9869e4a 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -41,6 +41,11 @@ //! The pool admin may adjust the pool configuration such as reward rate per block, expiry block, //! and admin. //! +//! ## Disambiguation +//! +//! While this pallet shares some terminology with the `staking-pool` and similar native staking +//! related pallets, it is distinct and is entirely unrelated to native staking. +//! //! ## Permissioning //! //! Currently, pool creation and management restricted to a configured Origin. From 21c21ae2e342871f01d64d520d47c55f79954d80 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 15:26:44 +0400 Subject: [PATCH 089/159] add test for same staking and reward asset --- substrate/frame/asset-rewards/src/tests.rs | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 417d4185e57e..906ee8d75e75 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -220,6 +220,57 @@ mod create_pool { }); } + #[test] + fn success_same_assest() { + new_test_ext().execute_with(|| { + assert_eq!(NextPoolId::::get(), 0); + + // Create a pool with the same staking and reward asset. + let asset = NativeOrWithId::::Native; + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::root(), + Box::new(asset.clone()), + Box::new(asset.clone()), + DEFAULT_REWARD_RATE_PER_BLOCK, + DEFAULT_EXPIRY_BLOCK, + None + )); + + // Event is emitted. + assert_eq!( + events(), + [Event::::PoolCreated { + creator: PermissionedAccountId::get(), + pool_id: 0, + staked_asset_id: asset.clone(), + reward_asset_id: asset.clone(), + reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, + expiry_block: DEFAULT_EXPIRY_BLOCK, + admin: PermissionedAccountId::get(), + }] + ); + + // State is updated correctly. + assert_eq!(NextPoolId::::get(), 1); + assert_eq!( + pools(), + vec![( + 0, + PoolInfo { + staked_asset_id: asset.clone(), + reward_asset_id: asset, + reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, + expiry_block: DEFAULT_EXPIRY_BLOCK, + admin: PermissionedAccountId::get(), + total_tokens_staked: 0, + reward_per_token_stored: 0, + last_update_block: 0 + } + )] + ); + }) + } + #[test] fn fails_for_non_existent_asset() { new_test_ext().execute_with(|| { From 8c72832dd59d7910717e60f7068ff05adc8050fd Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 15:34:11 +0400 Subject: [PATCH 090/159] make admin Option --- substrate/frame/asset-rewards/src/lib.rs | 25 ++++++++++++---------- substrate/frame/asset-rewards/src/tests.rs | 24 ++++++++++----------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 472bf9869e4a..d15abb28d463 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -145,7 +145,10 @@ pub struct PoolInfo { /// The block the pool will cease distributing rewards. expiry_block: BlockNumber, /// The permissioned account that can manage this pool. - admin: AccountId, + /// + /// This is currently always `Some`, and only an `Option` so in the future permissionless + /// pools may be enabled without storage migration. + admin: Option, /// The total amount of tokens staked in this pool. total_tokens_staked: Balance, /// Total rewards accumulated per token, up to the `last_update_block`. @@ -273,7 +276,7 @@ pub mod pallet { /// The block the pool will cease to accumulate rewards. expiry_block: BlockNumberFor, /// The account allowed to modify the pool. - admin: T::AccountId, + admin: Option, }, /// A pool reward rate was modified by the admin. PoolRewardRateModified { @@ -287,7 +290,7 @@ pub mod pallet { /// The modified pool. pool_id: PoolId, /// The new admin. - new_admin: T::AccountId, + new_admin: Option, }, /// A pool expiry block was modified by the admin. PoolExpiryBlockModified { @@ -360,7 +363,7 @@ pub mod pallet { reward_per_token_stored: 0u32.into(), last_update_block: 0u32.into(), expiry_block, - admin: admin.clone(), + admin: Some(admin.clone()), }; // Insert it into storage. @@ -376,7 +379,7 @@ pub mod pallet { reward_asset_id: *reward_asset_id, reward_rate_per_block, expiry_block, - admin, + admin: Some(admin), }); Ok(()) @@ -508,7 +511,7 @@ pub mod pallet { .or_else(|_| ensure_signed(origin))?; let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(caller == pool_info.admin, BadOrigin); + ensure!(Some(caller) == pool_info.admin, BadOrigin); // Always start by updating the pool rewards. let rewards_per_token = Self::reward_per_token(&pool_info)?; @@ -538,11 +541,11 @@ pub mod pallet { .or_else(|_| ensure_signed(origin))?; let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin == caller, BadOrigin); - pool_info.admin = new_admin.clone(); + ensure!(pool_info.admin == Some(caller), BadOrigin); + pool_info.admin = Some(new_admin.clone()); Pools::::insert(pool_id, pool_info); - Self::deposit_event(Event::PoolAdminModified { pool_id, new_admin }); + Self::deposit_event(Event::PoolAdminModified { pool_id, new_admin: Some(new_admin) }); Ok(()) } @@ -565,7 +568,7 @@ pub mod pallet { ); let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin == caller, BadOrigin); + ensure!(pool_info.admin == Some(caller), BadOrigin); // Always start by updating the pool rewards. let reward_per_token = Self::reward_per_token(&pool_info)?; @@ -617,7 +620,7 @@ pub mod pallet { .or_else(|_| ensure_signed(origin))?; let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin == caller, BadOrigin); + ensure!(pool_info.admin == Some(caller), BadOrigin); T::Assets::transfer( pool_info.reward_asset_id, diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 906ee8d75e75..583581a8df8a 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -132,7 +132,7 @@ mod create_pool { reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: DEFAULT_EXPIRY_BLOCK, - admin: PermissionedAccountId::get(), + admin: Some(PermissionedAccountId::get()), }] ); @@ -147,7 +147,7 @@ mod create_pool { reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: DEFAULT_EXPIRY_BLOCK, - admin: PermissionedAccountId::get(), + admin: Some(PermissionedAccountId::get()), total_tokens_staked: 0, reward_per_token_stored: 0, last_update_block: 0 @@ -179,7 +179,7 @@ mod create_pool { staked_asset_id: staked_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, - admin, + admin: Some(admin), expiry_block, }] ); @@ -195,7 +195,7 @@ mod create_pool { staked_asset_id: DEFAULT_STAKED_ASSET_ID, reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, - admin: PermissionedAccountId::get(), + admin: Some(PermissionedAccountId::get()), expiry_block: DEFAULT_EXPIRY_BLOCK, total_tokens_staked: 0, reward_per_token_stored: 0, @@ -208,7 +208,7 @@ mod create_pool { staked_asset_id, reward_asset_id, reward_rate_per_block, - admin, + admin: Some(admin), total_tokens_staked: 0, expiry_block, reward_per_token_stored: 0, @@ -246,7 +246,7 @@ mod create_pool { reward_asset_id: asset.clone(), reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: DEFAULT_EXPIRY_BLOCK, - admin: PermissionedAccountId::get(), + admin: Some(PermissionedAccountId::get()), }] ); @@ -261,7 +261,7 @@ mod create_pool { reward_asset_id: asset, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: DEFAULT_EXPIRY_BLOCK, - admin: PermissionedAccountId::get(), + admin: Some(PermissionedAccountId::get()), total_tokens_staked: 0, reward_per_token_stored: 0, last_update_block: 0 @@ -637,9 +637,9 @@ mod set_pool_admin { // Check state assert_eq!( *events().last().unwrap(), - Event::::PoolAdminModified { pool_id, new_admin } + Event::::PoolAdminModified { pool_id, new_admin: Some(new_admin) } ); - assert_eq!(Pools::::get(pool_id).unwrap().admin, new_admin); + assert_eq!(Pools::::get(pool_id).unwrap().admin, Some(new_admin)); }); } @@ -656,9 +656,9 @@ mod set_pool_admin { // Check state assert_eq!( *events().last().unwrap(), - Event::::PoolAdminModified { pool_id, new_admin } + Event::::PoolAdminModified { pool_id, new_admin: Some(new_admin) } ); - assert_eq!(Pools::::get(pool_id).unwrap().admin, new_admin); + assert_eq!(Pools::::get(pool_id).unwrap().admin, Some(new_admin)); }); } @@ -1373,7 +1373,7 @@ fn integration() { reward_asset_id, reward_rate_per_block: 100, expiry_block: 25, - admin + admin: Some(admin) }, Event::Staked { who: staker1, pool_id, amount: 100 }, Event::Staked { who: staker2, pool_id, amount: 100 }, From bb215364185a6137b00b268c6c56f69a08f50090 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 16:12:42 +0400 Subject: [PATCH 091/159] rename createpoolorigin --- .../runtimes/assets/asset-hub-rococo/src/lib.rs | 2 +- .../runtimes/assets/asset-hub-westend/src/lib.rs | 2 +- substrate/bin/node/runtime/src/lib.rs | 2 +- substrate/frame/asset-rewards/src/benchmarking.rs | 10 ++++++---- substrate/frame/asset-rewards/src/lib.rs | 12 ++++++------ substrate/frame/asset-rewards/src/mock.rs | 2 +- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 8df40f677f68..ed9b50fae202 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -938,7 +938,7 @@ impl pallet_asset_rewards::Config for Runtime { type Balance = Balance; type Assets = NativeAndAllAssets; type AssetId = xcm::v3::Location; - type PermissionedOrigin = EnsureWithSuccess< + type CreatePoolOrigin = EnsureWithSuccess< EitherOfDiverse< EnsureRoot, EnsureXcm>, 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 b6b4f7eab3d1..2319e6cd8a69 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -393,7 +393,7 @@ impl pallet_asset_rewards::Config for Runtime { type Balance = Balance; type Assets = NativeAndAllAssets; type AssetId = xcm::v3::Location; - type PermissionedOrigin = EnsureWithSuccess< + type CreatePoolOrigin = EnsureWithSuccess< EitherOfDiverse< EnsureRoot, EnsureXcm>, diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 096b43a3739a..26feeaf28136 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1782,7 +1782,7 @@ impl pallet_asset_rewards::Config for Runtime { type Balance = u128; type Assets = NativeAndAssets; type PalletId = StakingRewardsPalletId; - type PermissionedOrigin = AssetRewardsPermissionedOrigin; + type CreatePoolOrigin = AssetRewardsPermissionedOrigin; type WeightInfo = (); #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = AssetRewardsBenchmarkHelper; diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 278c2a2e7bff..2ebae50d5c7f 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -17,7 +17,7 @@ //! Asset Rewards pallet benchmarking. //! -//! Note: these benchmarks assume that Root passes the `PermissionedOrigin` checks. +//! Note: these benchmarks assume that Root passes the `CreatePoolOrigin` checks. use super::*; use crate::Pallet as AssetRewards; @@ -87,7 +87,7 @@ mod benchmarks { fn create_pool() { use super::*; - let root_acc = T::PermissionedOrigin::ensure_origin(Root.into()).unwrap(); + let root_acc = T::CreatePoolOrigin::ensure_origin(Root.into()).unwrap(); let staked_asset = T::BenchmarkHelper::to_asset_id(1); let reward_asset = T::BenchmarkHelper::to_asset_id(2); create_and_mint_asset::( @@ -114,7 +114,7 @@ mod benchmarks { assert_last_event::( Event::PoolCreated { creator: root_acc.clone(), - admin: root_acc, + admin: Some(root_acc), staked_asset_id: staked_asset, reward_asset_id: reward_asset, reward_rate_per_block: 100u32.into(), @@ -328,7 +328,9 @@ mod benchmarks { #[extrinsic_call] _(Root, 0u32.into(), new_admin.clone()); - assert_last_event::(Event::PoolAdminModified { pool_id: 0u32.into(), new_admin }.into()); + assert_last_event::( + Event::PoolAdminModified { pool_id: 0u32.into(), new_admin: Some(new_admin) }.into(), + ); } #[benchmark] diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index d15abb28d463..692d54c708b8 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -193,7 +193,7 @@ pub mod pallet { /// /// The Origin must return an AccountId. This can be achieved for any Origin by wrapping it /// with `EnsureSuccess`. - type PermissionedOrigin: EnsureOrigin; + type CreatePoolOrigin: EnsureOrigin; /// Registry of assets that can be configured to either stake for rewards, or be offered as /// rewards for staking. @@ -333,7 +333,7 @@ pub mod pallet { admin: Option, ) -> DispatchResult { // Check the origin. - let creator = T::PermissionedOrigin::ensure_origin(origin.clone())?; + let creator = T::CreatePoolOrigin::ensure_origin(origin.clone())?; // Ensure the assets exist. ensure!( @@ -507,7 +507,7 @@ pub mod pallet { pool_id: PoolId, new_reward_rate_per_block: T::Balance, ) -> DispatchResult { - let caller = T::PermissionedOrigin::ensure_origin(origin.clone()) + let caller = T::CreatePoolOrigin::ensure_origin(origin.clone()) .or_else(|_| ensure_signed(origin))?; let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; @@ -537,7 +537,7 @@ pub mod pallet { pool_id: PoolId, new_admin: T::AccountId, ) -> DispatchResult { - let caller = T::PermissionedOrigin::ensure_origin(origin.clone()) + let caller = T::CreatePoolOrigin::ensure_origin(origin.clone()) .or_else(|_| ensure_signed(origin))?; let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; @@ -559,7 +559,7 @@ pub mod pallet { pool_id: PoolId, new_expiry_block: BlockNumberFor, ) -> DispatchResult { - let caller = T::PermissionedOrigin::ensure_origin(origin.clone()) + let caller = T::CreatePoolOrigin::ensure_origin(origin.clone()) .or_else(|_| ensure_signed(origin))?; ensure!( @@ -616,7 +616,7 @@ pub mod pallet { amount: T::Balance, dest: T::AccountId, ) -> DispatchResult { - let caller = T::PermissionedOrigin::ensure_origin(origin.clone()) + let caller = T::CreatePoolOrigin::ensure_origin(origin.clone()) .or_else(|_| ensure_signed(origin))?; let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index 32f1c7913d9e..ac643bdf685b 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -149,7 +149,7 @@ impl Config for MockRuntime { type Balance = ::Balance; type Assets = NativeAndAssets; type PalletId = StakingRewardsPalletId; - type PermissionedOrigin = MockPermissionedOrigin; + type CreatePoolOrigin = MockPermissionedOrigin; type WeightInfo = (); #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = AssetRewardsBenchmarkHelper; From 78f642beb8a98a507beb4615b3bf6b1f9c8c5d0e Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 16:40:59 +0400 Subject: [PATCH 092/159] rename who to caller --- .../frame/asset-rewards/src/benchmarking.rs | 6 ++--- substrate/frame/asset-rewards/src/lib.rs | 12 +++++----- substrate/frame/asset-rewards/src/tests.rs | 22 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 2ebae50d5c7f..3d9af4fc4719 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -156,7 +156,7 @@ mod benchmarks { _(RawOrigin::Signed(staker.clone()), 0u32.into(), 100u32.into()); assert_last_event::( - Event::Staked { who: staker, pool_id: 0u32.into(), amount: 100u32.into() }.into(), + Event::Staked { caller: staker, pool_id: 0u32.into(), amount: 100u32.into() }.into(), ); } @@ -197,7 +197,7 @@ mod benchmarks { _(RawOrigin::Signed(staker.clone()), 0u32.into(), 100u32.into()); assert_last_event::( - Event::Unstaked { who: staker, pool_id: 0u32.into(), amount: 100u32.into() }.into(), + Event::Unstaked { caller: staker, pool_id: 0u32.into(), amount: 100u32.into() }.into(), ); } @@ -250,7 +250,7 @@ mod benchmarks { assert_last_event::( Event::RewardsHarvested { - who: staker.clone(), + caller: staker.clone(), staker, pool_id: 0u32.into(), amount: (blocks_elapsed * 100u8.into()).saturated_into::().into(), diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 692d54c708b8..adc1c0f4e194 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -235,7 +235,7 @@ pub mod pallet { /// An account staked some tokens in a pool. Staked { /// The account that staked assets. - who: T::AccountId, + caller: T::AccountId, /// The pool. pool_id: PoolId, /// The staked asset amount. @@ -244,7 +244,7 @@ pub mod pallet { /// An account unstaked some tokens from a pool. Unstaked { /// The account that unstaked assets. - who: T::AccountId, + caller: T::AccountId, /// The pool. pool_id: PoolId, /// The unstaked asset amount. @@ -253,7 +253,7 @@ pub mod pallet { /// An account harvested some rewards. RewardsHarvested { /// The caller. - who: T::AccountId, + caller: T::AccountId, /// The staker whos rewards were harvested. staker: T::AccountId, /// The pool. @@ -410,7 +410,7 @@ pub mod pallet { PoolStakers::::insert(pool_id, &caller, staker_info); // Emit event. - Self::deposit_event(Event::Staked { who: caller, pool_id, amount }); + Self::deposit_event(Event::Staked { caller, pool_id, amount }); Ok(()) } @@ -447,7 +447,7 @@ pub mod pallet { PoolStakers::::insert(pool_id, &caller, staker_info); // Emit event. - Self::deposit_event(Event::Unstaked { who: caller, pool_id, amount }); + Self::deposit_event(Event::Unstaked { caller, pool_id, amount }); Ok(()) } @@ -485,7 +485,7 @@ pub mod pallet { // Emit event. Self::deposit_event(Event::RewardsHarvested { - who: caller.clone(), + caller: caller.clone(), staker, pool_id, amount: staker_info.rewards, diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 583581a8df8a..ff55cf46edc5 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -376,7 +376,7 @@ mod stake { // Event is emitted. assert_eq!( *events().last().unwrap(), - Event::::Staked { who: user, amount: 1000, pool_id: 0 } + Event::::Staked { caller: user, amount: 1000, pool_id: 0 } ); // Check that the pool's total tokens staked is updated @@ -390,7 +390,7 @@ mod stake { // Event is emitted. assert_eq!( *events().last().unwrap(), - Event::::Staked { who: user, amount: 500, pool_id: 0 } + Event::::Staked { caller: user, amount: 500, pool_id: 0 } ); // Check that the user's staked amount is updated @@ -442,7 +442,7 @@ mod unstake { // Event is emitted. assert_eq!( *events().last().unwrap(), - Event::::Unstaked { who: user, amount: 500, pool_id: 0 } + Event::::Unstaked { caller: user, amount: 500, pool_id: 0 } ); // Check that the user's staked amount is updated @@ -530,7 +530,7 @@ mod harvest_rewards { assert_eq!( *events().last().unwrap(), Event::::RewardsHarvested { - who: staker, + caller: staker, staker, pool_id, amount: 10 * Pools::::get(pool_id).unwrap().reward_rate_per_block @@ -572,7 +572,7 @@ mod harvest_rewards { assert_eq!( *events().last().unwrap(), Event::::RewardsHarvested { - who: harvester, + caller: harvester, staker, pool_id, amount: 10 * Pools::::get(pool_id).unwrap().reward_rate_per_block @@ -1375,14 +1375,14 @@ fn integration() { expiry_block: 25, admin: Some(admin) }, - Event::Staked { who: staker1, pool_id, amount: 100 }, - Event::Staked { who: staker2, pool_id, amount: 100 }, - Event::Staked { who: staker1, pool_id, amount: 100 }, - Event::Unstaked { who: staker1, pool_id, amount: 100 }, - Event::Unstaked { who: staker1, pool_id, amount: 100 }, + Event::Staked { caller: staker1, pool_id, amount: 100 }, + Event::Staked { caller: staker2, pool_id, amount: 100 }, + Event::Staked { caller: staker1, pool_id, amount: 100 }, + Event::Unstaked { caller: staker1, pool_id, amount: 100 }, + Event::Unstaked { caller: staker1, pool_id, amount: 100 }, Event::PoolExpiryBlockModified { pool_id, new_expiry_block: 60 }, Event::PoolRewardRateModified { pool_id, new_reward_rate_per_block: 50 }, - Event::RewardsHarvested { who: staker2, staker: staker2, pool_id, amount: 1233 } + Event::RewardsHarvested { caller: staker2, staker: staker2, pool_id, amount: 1233 } ] ); }); From cfabe6f82bf5190cfaf7dfe6a6ef90d1792fd1e6 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 17:06:45 +0400 Subject: [PATCH 093/159] create_pool take lifetime --- .../frame/asset-rewards/src/benchmarking.rs | 3 +- substrate/frame/asset-rewards/src/lib.rs | 7 +- substrate/frame/asset-rewards/src/tests.rs | 69 ++++++++----------- 3 files changed, 37 insertions(+), 42 deletions(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 3d9af4fc4719..c6d2debcda28 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -101,6 +101,7 @@ mod benchmarks { T::Assets::minimum_balance(reward_asset.clone()), ); + let block_number_before = frame_system::Pallet::::block_number(); #[extrinsic_call] _( Root, @@ -118,7 +119,7 @@ mod benchmarks { staked_asset_id: staked_asset, reward_asset_id: reward_asset, reward_rate_per_block: 100u32.into(), - expiry_block: 200u32.into(), + expiry_block: block_number_before + 200u32.into(), pool_id: 0u32.into(), } .into(), diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index adc1c0f4e194..7ff3e1937103 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -323,13 +323,16 @@ pub mod pallet { /// Create a new reward pool. /// /// If an explicity admin is not specified, it defaults to the caller. + /// + /// The initial pool expiry will be calculated by summing `pool_lifetime` with the block + /// number at the time of execution. #[pallet::call_index(0)] pub fn create_pool( origin: OriginFor, staked_asset_id: Box, reward_asset_id: Box, reward_rate_per_block: T::Balance, - expiry_block: BlockNumberFor, + pool_lifetime: BlockNumberFor, admin: Option, ) -> DispatchResult { // Check the origin. @@ -346,6 +349,8 @@ pub mod pallet { ); // Check the expiry block. + let expiry_block = + frame_system::Pallet::::block_number().saturating_add(pool_lifetime); ensure!( expiry_block > frame_system::Pallet::::block_number(), Error::::ExpiryBlockMustBeInTheFuture diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index ff55cf46edc5..7bd661d68322 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -22,14 +22,14 @@ use sp_runtime::{traits::BadOrigin, ArithmeticError, TokenError}; const DEFAULT_STAKED_ASSET_ID: NativeOrWithId = NativeOrWithId::::WithId(1); const DEFAULT_REWARD_ASSET_ID: NativeOrWithId = NativeOrWithId::::Native; const DEFAULT_REWARD_RATE_PER_BLOCK: u128 = 100; -const DEFAULT_EXPIRY_BLOCK: u64 = 200; +const DEFAULT_LIFETIME: u64 = 200; const DEFAULT_ADMIN: u128 = 1; /// Creates a basic pool with values: /// - Staking asset: 1 /// - Reward asset: Native /// - Reward rate per block: 100 -/// - Expiry block: 100 +/// - Lifetime: 100 /// - Admin: 1 /// /// Useful to reduce boilerplate in tests when it's not important to customise or reuse pool @@ -40,7 +40,7 @@ pub fn create_default_pool() { Box::new(DEFAULT_STAKED_ASSET_ID.clone()), Box::new(DEFAULT_REWARD_ASSET_ID.clone()), DEFAULT_REWARD_RATE_PER_BLOCK, - DEFAULT_EXPIRY_BLOCK, + DEFAULT_LIFETIME, Some(DEFAULT_ADMIN) )); } @@ -52,7 +52,7 @@ pub fn create_default_pool_permissioned_admin() { Box::new(DEFAULT_STAKED_ASSET_ID.clone()), Box::new(DEFAULT_REWARD_ASSET_ID.clone()), DEFAULT_REWARD_RATE_PER_BLOCK, - DEFAULT_EXPIRY_BLOCK, + DEFAULT_LIFETIME, None )); } @@ -111,6 +111,9 @@ mod create_pool { new_test_ext().execute_with(|| { assert_eq!(NextPoolId::::get(), 0); + System::set_block_number(10); + let expected_expiry_block = DEFAULT_LIFETIME + 10; + // Create a pool with default values, and no admin override so [`PermissionedAccountId`] // is admin. assert_ok!(StakingRewards::create_pool( @@ -118,7 +121,7 @@ mod create_pool { Box::new(DEFAULT_STAKED_ASSET_ID), Box::new(DEFAULT_REWARD_ASSET_ID), DEFAULT_REWARD_RATE_PER_BLOCK, - DEFAULT_EXPIRY_BLOCK, + DEFAULT_LIFETIME, None )); @@ -131,7 +134,7 @@ mod create_pool { staked_asset_id: DEFAULT_STAKED_ASSET_ID, reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, - expiry_block: DEFAULT_EXPIRY_BLOCK, + expiry_block: expected_expiry_block, admin: Some(PermissionedAccountId::get()), }] ); @@ -146,7 +149,7 @@ mod create_pool { staked_asset_id: DEFAULT_STAKED_ASSET_ID, reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, - expiry_block: DEFAULT_EXPIRY_BLOCK, + expiry_block: expected_expiry_block, admin: Some(PermissionedAccountId::get()), total_tokens_staked: 0, reward_per_token_stored: 0, @@ -161,6 +164,7 @@ mod create_pool { let reward_asset_id = NativeOrWithId::::WithId(20); let reward_rate_per_block = 250; let expiry_block = 500; + let expected_expiry_block = expiry_block + 10; assert_ok!(StakingRewards::create_pool( RuntimeOrigin::root(), Box::new(staked_asset_id.clone()), @@ -180,7 +184,7 @@ mod create_pool { reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, admin: Some(admin), - expiry_block, + expiry_block: expected_expiry_block, }] ); @@ -196,7 +200,7 @@ mod create_pool { reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, admin: Some(PermissionedAccountId::get()), - expiry_block: DEFAULT_EXPIRY_BLOCK, + expiry_block: DEFAULT_LIFETIME + 10, total_tokens_staked: 0, reward_per_token_stored: 0, last_update_block: 0 @@ -210,7 +214,7 @@ mod create_pool { reward_rate_per_block, admin: Some(admin), total_tokens_staked: 0, - expiry_block, + expiry_block: expected_expiry_block, reward_per_token_stored: 0, last_update_block: 0 } @@ -221,10 +225,13 @@ mod create_pool { } #[test] - fn success_same_assest() { + fn success_same_assets() { new_test_ext().execute_with(|| { assert_eq!(NextPoolId::::get(), 0); + System::set_block_number(10); + let expected_expiry_block = DEFAULT_LIFETIME + 10; + // Create a pool with the same staking and reward asset. let asset = NativeOrWithId::::Native; assert_ok!(StakingRewards::create_pool( @@ -232,7 +239,7 @@ mod create_pool { Box::new(asset.clone()), Box::new(asset.clone()), DEFAULT_REWARD_RATE_PER_BLOCK, - DEFAULT_EXPIRY_BLOCK, + DEFAULT_LIFETIME, None )); @@ -245,7 +252,7 @@ mod create_pool { staked_asset_id: asset.clone(), reward_asset_id: asset.clone(), reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, - expiry_block: DEFAULT_EXPIRY_BLOCK, + expiry_block: expected_expiry_block, admin: Some(PermissionedAccountId::get()), }] ); @@ -260,7 +267,7 @@ mod create_pool { staked_asset_id: asset.clone(), reward_asset_id: asset, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, - expiry_block: DEFAULT_EXPIRY_BLOCK, + expiry_block: expected_expiry_block, admin: Some(PermissionedAccountId::get()), total_tokens_staked: 0, reward_per_token_stored: 0, @@ -336,25 +343,6 @@ mod create_pool { ); }); } - - #[test] - fn fails_for_bad_expiry_block() { - new_test_ext().execute_with(|| { - let expiry_block = 100u64; - System::set_block_number(expiry_block + 1u64); - assert_err!( - StakingRewards::create_pool( - RuntimeOrigin::root(), - Box::new(DEFAULT_STAKED_ASSET_ID), - Box::new(DEFAULT_REWARD_ASSET_ID), - DEFAULT_REWARD_RATE_PER_BLOCK, - expiry_block, - None - ), - Error::::ExpiryBlockMustBeInTheFuture - ); - }); - } } mod stake { @@ -755,10 +743,10 @@ mod set_pool_expiry_block { let staker = 2; let pool_id = 0; let new_expiry_block = 300u64; + System::set_block_number(10); create_default_pool(); // Regular reward accumulation - System::set_block_number(10); assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker), pool_id, 1000)); System::set_block_number(20); assert_hypothetically_earned( @@ -768,11 +756,11 @@ mod set_pool_expiry_block { NativeOrWithId::::Native, ); - // Expiry was block 200, so earned 190 at block 250 + // Expiry was block 210, so earned 200 at block 250 System::set_block_number(250); assert_hypothetically_earned( staker, - DEFAULT_REWARD_RATE_PER_BLOCK * 190, + DEFAULT_REWARD_RATE_PER_BLOCK * 200, pool_id, NativeOrWithId::::Native, ); @@ -785,10 +773,10 @@ mod set_pool_expiry_block { )); System::set_block_number(350); - // Staker has been in pool with rewards active for 240 blocks total + // Staker has been in pool with rewards active for 250 blocks total assert_hypothetically_earned( staker, - DEFAULT_REWARD_RATE_PER_BLOCK * 240, + DEFAULT_REWARD_RATE_PER_BLOCK * 250, pool_id, NativeOrWithId::::Native, ); @@ -1234,13 +1222,14 @@ fn integration() { let staked_asset_id = NativeOrWithId::::WithId(1); let reward_asset_id = NativeOrWithId::::Native; let reward_rate_per_block = 100; - let expiry_block = 25u64.into(); + let lifetime = 24u64.into(); + System::set_block_number(1); assert_ok!(StakingRewards::create_pool( RuntimeOrigin::root(), Box::new(staked_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, - expiry_block, + lifetime, Some(admin) )); let pool_id = 0; From 10f9bfc50e3a02460aece0b5083583204e9f23d0 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 17:10:10 +0400 Subject: [PATCH 094/159] handle overflow --- substrate/frame/asset-rewards/src/lib.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 7ff3e1937103..1cb471716c2b 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -95,7 +95,10 @@ use frame_support::{ }; use scale_info::TypeInfo; use sp_core::Get; -use sp_runtime::{traits::Zero, DispatchError}; +use sp_runtime::{ + traits::{CheckedAdd, Zero}, + DispatchError, +}; use sp_std::boxed::Box; #[cfg(feature = "runtime-benchmarks")] @@ -315,6 +318,8 @@ pub mod pallet { BlockNumberConversionError, /// The expiry block must be in the future. ExpiryBlockMustBeInTheFuture, + /// An amount overflowed. + Overflow, } /// Pallet's callable functions. @@ -407,7 +412,9 @@ pub mod pallet { // TODO: (blocked https://github.com/paritytech/polkadot-sdk/issues/3342) // Update Pools. - pool_info.total_tokens_staked.saturating_accrue(amount); + pool_info.total_tokens_staked = + pool_info.total_tokens_staked.checked_add(&amount).ok_or(Error::::Overflow)?; + Pools::::insert(pool_id, pool_info); // Update PoolStakers. From a307dc5a20f66b8ca450d7075fea77fb179d6fc6 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 17:13:29 +0400 Subject: [PATCH 095/159] transfer expendable --- substrate/frame/asset-rewards/src/lib.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 1cb471716c2b..c20eae3f772d 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -492,7 +492,8 @@ pub mod pallet { &pool_account_id, &staker, staker_info.rewards, - Preservation::Preserve, + // Could kill the account, but only if the pool was already almost empty. + Preservation::Expendable, )?; // Emit event. @@ -639,7 +640,8 @@ pub mod pallet { &Self::pool_account_id(&pool_id)?, &dest, amount, - Preservation::Preserve, + // Allow completely draining the account. + Preservation::Expendable, )?; Ok(()) From 9767838b0ef90f005e6dd23947ef6872948c346e Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 17 Apr 2024 17:21:26 +0400 Subject: [PATCH 096/159] integrity test --- substrate/frame/asset-rewards/src/lib.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index c20eae3f772d..bc25faebc8e9 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -322,6 +322,20 @@ pub mod pallet { Overflow, } + #[pallet::hooks] + impl Hooks> for Pallet { + fn integrity_test() { + // The AccountId is at least 8 bytes to contain the unique PalletId. + match >::try_into_account( + &T::PalletId::get(), + ) { + // Some(_) => (), + Some(_) => (), + None => panic!("pallet_asset_rewards: PalletId must be at least 8 bytes"), + } + } + } + /// Pallet's callable functions. #[pallet::call(weight(::WeightInfo))] impl Pallet { From e8e508815f4d838c8766b437718a8b2d08dd0b3e Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 19 Apr 2024 08:58:15 +0400 Subject: [PATCH 097/159] clippy --- substrate/frame/asset-rewards/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index bc25faebc8e9..2deee0f4a35d 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -685,7 +685,7 @@ pub mod pallet { staker_info: &PoolStakerInfo, ) -> Result<(PoolInfoFor, PoolStakerInfo), DispatchError> { let reward_per_token = Self::reward_per_token(&pool_info)?; - let pool_info = Self::update_pool_rewards(pool_info, reward_per_token.clone())?; + let pool_info = Self::update_pool_rewards(pool_info, reward_per_token)?; let mut new_staker_info = staker_info.clone(); new_staker_info.rewards = Self::derive_rewards(&staker_info, &reward_per_token)?; From 98d705da0f40bea71f47951ea22ae6a6c507b9b5 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 19 Apr 2024 09:55:13 +0400 Subject: [PATCH 098/159] clippy --- Cargo.lock | 13 +++++++------ .../src/tests/treasury_asset_reward_pool.rs | 4 ++-- .../src/tests/treasury_asset_reward_pool.rs | 4 ++-- substrate/bin/node/runtime/src/lib.rs | 2 +- substrate/frame/asset-rewards/src/lib.rs | 7 +++---- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f8810fa16f1..a7a9bb316e6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7633,9 +7633,9 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "libnghttp2-sys" -version = "0.1.9+1.58.0" +version = "0.1.10+1.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b57e858af2798e167e709b9d969325b6d8e9d50232fcbc494d7d54f976854a64" +checksum = "959c25552127d2e1fa72f0e52548ec04fc386e827ba71a7bd01db46a447dc135" dependencies = [ "cc", "libc", @@ -21739,10 +21739,11 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ + "cfg-if", "log", "pin-project-lite 0.2.12", "tracing-attributes", @@ -21751,9 +21752,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2 1.0.75", "quote 1.0.35", diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs index 4dd23dbca78e..2fa9c76ecfdf 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs @@ -33,7 +33,7 @@ fn treasury_creates_asset_reward_pool() { let reward_asset_id = bx!(TokenLocationV3::get()); let reward_rate_per_block = 1_000_000_000; - let expiry_block = 1_000_000_000; + let lifetime = 1_000_000_000; let admin = None; let create_pool_call = @@ -51,7 +51,7 @@ fn treasury_creates_asset_reward_pool() { staked_asset_id, reward_asset_id, reward_rate_per_block, - expiry_block, + lifetime, admin } ) diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs index 9e9166da1872..2d14ebc2500e 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs @@ -33,7 +33,7 @@ fn treasury_creates_asset_reward_pool() { let reward_asset_id = bx!(WestendLocationV3::get()); let reward_rate_per_block = 1_000_000_000; - let expiry_block = 1_000_000_000; + let lifetime = 1_000_000_000; let admin = None; let create_pool_call = @@ -51,7 +51,7 @@ fn treasury_creates_asset_reward_pool() { staked_asset_id, reward_asset_id, reward_rate_per_block, - expiry_block, + lifetime, admin } ) diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 3fd27dceee9b..ee5d5064024c 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1795,7 +1795,7 @@ impl pallet_asset_rewards::Config for Runtime { type WeightInfo = (); #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = AssetRewardsBenchmarkHelper; -}; +} impl pallet_asset_conversion_ops::Config for Runtime { type RuntimeEvent = RuntimeEvent; diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 2deee0f4a35d..e37a81fa88f9 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -343,7 +343,7 @@ pub mod pallet { /// /// If an explicity admin is not specified, it defaults to the caller. /// - /// The initial pool expiry will be calculated by summing `pool_lifetime` with the block + /// The initial pool expiry will be calculated by summing `lifetime` with the block /// number at the time of execution. #[pallet::call_index(0)] pub fn create_pool( @@ -351,7 +351,7 @@ pub mod pallet { staked_asset_id: Box, reward_asset_id: Box, reward_rate_per_block: T::Balance, - pool_lifetime: BlockNumberFor, + lifetime: BlockNumberFor, admin: Option, ) -> DispatchResult { // Check the origin. @@ -368,8 +368,7 @@ pub mod pallet { ); // Check the expiry block. - let expiry_block = - frame_system::Pallet::::block_number().saturating_add(pool_lifetime); + let expiry_block = frame_system::Pallet::::block_number().saturating_add(lifetime); ensure!( expiry_block > frame_system::Pallet::::block_number(), Error::::ExpiryBlockMustBeInTheFuture From dc08086a979356470b88e73257d10712a79ec18c Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 19 Apr 2024 09:58:21 +0400 Subject: [PATCH 099/159] fmt --- .../emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs | 2 +- .../runtimes/assets/asset-hub-rococo/src/weights/mod.rs | 2 +- .../runtimes/assets/asset-hub-westend/src/weights/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs index 89f32ccdfb51..5de2344a0c20 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs @@ -19,5 +19,5 @@ mod send; mod set_xcm_versions; mod swap; mod teleport; -mod treasury_asset_reward_pool; mod treasury; +mod treasury_asset_reward_pool; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs index e752cf2e0e51..39cae47bd025 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs @@ -20,8 +20,8 @@ pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; pub mod pallet_asset_conversion; -pub mod pallet_asset_rewards; pub mod pallet_asset_conversion_ops; +pub mod pallet_asset_rewards; pub mod pallet_assets_foreign; pub mod pallet_assets_local; pub mod pallet_assets_pool; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs index f7d49e328d49..7b5f1affbe66 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs @@ -19,8 +19,8 @@ pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; pub mod pallet_asset_conversion; -pub mod pallet_asset_rewards; pub mod pallet_asset_conversion_ops; +pub mod pallet_asset_rewards; pub mod pallet_assets_foreign; pub mod pallet_assets_local; pub mod pallet_assets_pool; From fa5c860f923585fc16c3e18236ab5241815ee723 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 7 May 2024 11:54:49 +0400 Subject: [PATCH 100/159] remove unused struct --- .../assets/asset-hub-rococo/src/xcm_config.rs | 218 ----------------- .../asset-hub-westend/src/xcm_config.rs | 223 ------------------ 2 files changed, 441 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 961347ffd83a..501ee9d83e88 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -265,224 +265,6 @@ impl Contains for ParentOrParentsPlurality { } } -/// A call filter for the XCM Transact instruction. This is a temporary measure until we properly -/// account for proof size weights. -/// -/// Calls that are allowed through this filter must: -/// 1. Have a fixed weight; -/// 2. Cannot lead to another call being made; -/// 3. Have a defined proof size weight, e.g. no unbounded vecs in call parameters. -pub struct SafeCallFilter; -impl Contains for SafeCallFilter { - fn contains(call: &RuntimeCall) -> bool { - #[cfg(feature = "runtime-benchmarks")] - { - if matches!(call, RuntimeCall::System(frame_system::Call::remark_with_event { .. })) { - return true - } - } - - // Allow to change dedicated storage items (called by governance-like) - match call { - RuntimeCall::System(frame_system::Call::set_storage { items }) - if items.iter().all(|(k, _)| { - k.eq(&bridging::XcmBridgeHubRouterByteFee::key()) || - k.eq(&bridging::XcmBridgeHubRouterBaseFee::key()) || - k.eq(&bridging::to_ethereum::BridgeHubEthereumBaseFee::key()) - }) => - return true, - _ => (), - }; - - matches!( - call, - RuntimeCall::AssetRewards(pallet_asset_rewards::Call::create_pool { .. }) | - RuntimeCall::PolkadotXcm( - pallet_xcm::Call::force_xcm_version { .. } | - pallet_xcm::Call::force_default_xcm_version { .. } - ) | RuntimeCall::System( - frame_system::Call::set_heap_pages { .. } | - frame_system::Call::set_code { .. } | - frame_system::Call::set_code_without_checks { .. } | - frame_system::Call::authorize_upgrade { .. } | - frame_system::Call::authorize_upgrade_without_checks { .. } | - frame_system::Call::kill_prefix { .. }, - ) | RuntimeCall::ParachainSystem(..) | - RuntimeCall::Timestamp(..) | - RuntimeCall::Balances(..) | - RuntimeCall::CollatorSelection(..) | - RuntimeCall::Session(pallet_session::Call::purge_keys { .. }) | - RuntimeCall::XcmpQueue(..) | - RuntimeCall::MessageQueue(..) | - RuntimeCall::Assets( - pallet_assets::Call::create { .. } | - pallet_assets::Call::force_create { .. } | - pallet_assets::Call::start_destroy { .. } | - pallet_assets::Call::destroy_accounts { .. } | - pallet_assets::Call::destroy_approvals { .. } | - pallet_assets::Call::finish_destroy { .. } | - pallet_assets::Call::block { .. } | - pallet_assets::Call::mint { .. } | - pallet_assets::Call::burn { .. } | - pallet_assets::Call::transfer { .. } | - pallet_assets::Call::transfer_keep_alive { .. } | - pallet_assets::Call::force_transfer { .. } | - pallet_assets::Call::freeze { .. } | - pallet_assets::Call::thaw { .. } | - pallet_assets::Call::freeze_asset { .. } | - pallet_assets::Call::thaw_asset { .. } | - pallet_assets::Call::transfer_ownership { .. } | - pallet_assets::Call::set_team { .. } | - pallet_assets::Call::set_metadata { .. } | - pallet_assets::Call::clear_metadata { .. } | - pallet_assets::Call::force_set_metadata { .. } | - pallet_assets::Call::force_clear_metadata { .. } | - pallet_assets::Call::force_asset_status { .. } | - pallet_assets::Call::approve_transfer { .. } | - pallet_assets::Call::cancel_approval { .. } | - pallet_assets::Call::force_cancel_approval { .. } | - pallet_assets::Call::transfer_approved { .. } | - pallet_assets::Call::touch { .. } | - pallet_assets::Call::touch_other { .. } | - pallet_assets::Call::refund { .. } | - pallet_assets::Call::refund_other { .. }, - ) | RuntimeCall::ForeignAssets( - pallet_assets::Call::create { .. } | - pallet_assets::Call::force_create { .. } | - pallet_assets::Call::start_destroy { .. } | - pallet_assets::Call::destroy_accounts { .. } | - pallet_assets::Call::destroy_approvals { .. } | - pallet_assets::Call::finish_destroy { .. } | - pallet_assets::Call::block { .. } | - pallet_assets::Call::mint { .. } | - pallet_assets::Call::burn { .. } | - pallet_assets::Call::transfer { .. } | - pallet_assets::Call::transfer_keep_alive { .. } | - pallet_assets::Call::force_transfer { .. } | - pallet_assets::Call::freeze { .. } | - pallet_assets::Call::thaw { .. } | - pallet_assets::Call::freeze_asset { .. } | - pallet_assets::Call::thaw_asset { .. } | - pallet_assets::Call::transfer_ownership { .. } | - pallet_assets::Call::set_team { .. } | - pallet_assets::Call::set_metadata { .. } | - pallet_assets::Call::clear_metadata { .. } | - pallet_assets::Call::force_set_metadata { .. } | - pallet_assets::Call::force_clear_metadata { .. } | - pallet_assets::Call::force_asset_status { .. } | - pallet_assets::Call::approve_transfer { .. } | - pallet_assets::Call::cancel_approval { .. } | - pallet_assets::Call::force_cancel_approval { .. } | - pallet_assets::Call::transfer_approved { .. } | - pallet_assets::Call::touch { .. } | - pallet_assets::Call::touch_other { .. } | - pallet_assets::Call::refund { .. } | - pallet_assets::Call::refund_other { .. }, - ) | RuntimeCall::PoolAssets( - pallet_assets::Call::force_create { .. } | - pallet_assets::Call::block { .. } | - pallet_assets::Call::burn { .. } | - pallet_assets::Call::transfer { .. } | - pallet_assets::Call::transfer_keep_alive { .. } | - pallet_assets::Call::force_transfer { .. } | - pallet_assets::Call::freeze { .. } | - pallet_assets::Call::thaw { .. } | - pallet_assets::Call::freeze_asset { .. } | - pallet_assets::Call::thaw_asset { .. } | - pallet_assets::Call::transfer_ownership { .. } | - pallet_assets::Call::set_team { .. } | - pallet_assets::Call::set_metadata { .. } | - pallet_assets::Call::clear_metadata { .. } | - pallet_assets::Call::force_set_metadata { .. } | - pallet_assets::Call::force_clear_metadata { .. } | - pallet_assets::Call::force_asset_status { .. } | - pallet_assets::Call::approve_transfer { .. } | - pallet_assets::Call::cancel_approval { .. } | - pallet_assets::Call::force_cancel_approval { .. } | - pallet_assets::Call::transfer_approved { .. } | - pallet_assets::Call::touch { .. } | - pallet_assets::Call::touch_other { .. } | - pallet_assets::Call::refund { .. } | - pallet_assets::Call::refund_other { .. }, - ) | RuntimeCall::AssetConversion( - pallet_asset_conversion::Call::create_pool { .. } | - pallet_asset_conversion::Call::add_liquidity { .. } | - pallet_asset_conversion::Call::remove_liquidity { .. } | - pallet_asset_conversion::Call::swap_tokens_for_exact_tokens { .. } | - pallet_asset_conversion::Call::swap_exact_tokens_for_tokens { .. }, - ) | RuntimeCall::NftFractionalization( - pallet_nft_fractionalization::Call::fractionalize { .. } | - pallet_nft_fractionalization::Call::unify { .. }, - ) | RuntimeCall::Nfts( - pallet_nfts::Call::create { .. } | - pallet_nfts::Call::force_create { .. } | - pallet_nfts::Call::destroy { .. } | - pallet_nfts::Call::mint { .. } | - pallet_nfts::Call::force_mint { .. } | - pallet_nfts::Call::burn { .. } | - pallet_nfts::Call::transfer { .. } | - pallet_nfts::Call::lock_item_transfer { .. } | - pallet_nfts::Call::unlock_item_transfer { .. } | - pallet_nfts::Call::lock_collection { .. } | - pallet_nfts::Call::transfer_ownership { .. } | - pallet_nfts::Call::set_team { .. } | - pallet_nfts::Call::force_collection_owner { .. } | - pallet_nfts::Call::force_collection_config { .. } | - pallet_nfts::Call::approve_transfer { .. } | - pallet_nfts::Call::cancel_approval { .. } | - pallet_nfts::Call::clear_all_transfer_approvals { .. } | - pallet_nfts::Call::lock_item_properties { .. } | - pallet_nfts::Call::set_attribute { .. } | - pallet_nfts::Call::force_set_attribute { .. } | - pallet_nfts::Call::clear_attribute { .. } | - pallet_nfts::Call::approve_item_attributes { .. } | - pallet_nfts::Call::cancel_item_attributes_approval { .. } | - pallet_nfts::Call::set_metadata { .. } | - pallet_nfts::Call::clear_metadata { .. } | - pallet_nfts::Call::set_collection_metadata { .. } | - pallet_nfts::Call::clear_collection_metadata { .. } | - pallet_nfts::Call::set_accept_ownership { .. } | - pallet_nfts::Call::set_collection_max_supply { .. } | - pallet_nfts::Call::update_mint_settings { .. } | - pallet_nfts::Call::set_price { .. } | - pallet_nfts::Call::buy_item { .. } | - pallet_nfts::Call::pay_tips { .. } | - pallet_nfts::Call::create_swap { .. } | - pallet_nfts::Call::cancel_swap { .. } | - pallet_nfts::Call::claim_swap { .. }, - ) | RuntimeCall::Uniques( - pallet_uniques::Call::create { .. } | - pallet_uniques::Call::force_create { .. } | - pallet_uniques::Call::destroy { .. } | - pallet_uniques::Call::mint { .. } | - pallet_uniques::Call::burn { .. } | - pallet_uniques::Call::transfer { .. } | - pallet_uniques::Call::freeze { .. } | - pallet_uniques::Call::thaw { .. } | - pallet_uniques::Call::freeze_collection { .. } | - pallet_uniques::Call::thaw_collection { .. } | - pallet_uniques::Call::transfer_ownership { .. } | - pallet_uniques::Call::set_team { .. } | - pallet_uniques::Call::approve_transfer { .. } | - pallet_uniques::Call::cancel_approval { .. } | - pallet_uniques::Call::force_item_status { .. } | - pallet_uniques::Call::set_attribute { .. } | - pallet_uniques::Call::clear_attribute { .. } | - pallet_uniques::Call::set_metadata { .. } | - pallet_uniques::Call::clear_metadata { .. } | - pallet_uniques::Call::set_collection_metadata { .. } | - pallet_uniques::Call::clear_collection_metadata { .. } | - pallet_uniques::Call::set_accept_ownership { .. } | - pallet_uniques::Call::set_collection_max_supply { .. } | - pallet_uniques::Call::set_price { .. } | - pallet_uniques::Call::buy_item { .. } - ) | RuntimeCall::ToWestendXcmRouter( - pallet_xcm_bridge_hub_router::Call::report_bridge_status { .. } - ) - ) - } -} - pub type Barrier = TrailingSetTopicAsId< DenyThenTry< DenyReserveTransferToRelayChain, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index 489c25ed8faf..49bf07cbe26d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -278,229 +278,6 @@ impl Contains for AmbassadorEntities { } } -/// A call filter for the XCM Transact instruction. This is a temporary measure until we properly -/// account for proof size weights. -/// -/// Calls that are allowed through this filter must: -/// 1. Have a fixed weight; -/// 2. Cannot lead to another call being made; -/// 3. Have a defined proof size weight, e.g. no unbounded vecs in call parameters. -pub struct SafeCallFilter; -impl Contains for SafeCallFilter { - fn contains(call: &RuntimeCall) -> bool { - #[cfg(feature = "runtime-benchmarks")] - { - if matches!(call, RuntimeCall::System(frame_system::Call::remark_with_event { .. })) { - return true - } - } - - // Allow to change dedicated storage items (called by governance-like) - match call { - RuntimeCall::System(frame_system::Call::set_storage { items }) - if items.iter().all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterByteFee::key())) || - items - .iter() - .all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterBaseFee::key())) => - return true, - _ => (), - }; - - matches!( - call, - RuntimeCall::AssetRewards(pallet_asset_rewards::Call::create_pool { .. }) | - RuntimeCall::PolkadotXcm( - pallet_xcm::Call::force_xcm_version { .. } | - pallet_xcm::Call::force_default_xcm_version { .. } - ) | RuntimeCall::System( - frame_system::Call::set_heap_pages { .. } | - frame_system::Call::set_code { .. } | - frame_system::Call::set_code_without_checks { .. } | - frame_system::Call::authorize_upgrade { .. } | - frame_system::Call::authorize_upgrade_without_checks { .. } | - frame_system::Call::kill_prefix { .. }, - ) | RuntimeCall::ParachainSystem(..) | - RuntimeCall::Timestamp(..) | - RuntimeCall::Balances(..) | - RuntimeCall::CollatorSelection(..) | - RuntimeCall::Session(pallet_session::Call::purge_keys { .. }) | - RuntimeCall::XcmpQueue(..) | - RuntimeCall::MessageQueue(..) | - RuntimeCall::Assets( - pallet_assets::Call::create { .. } | - pallet_assets::Call::force_create { .. } | - pallet_assets::Call::start_destroy { .. } | - pallet_assets::Call::destroy_accounts { .. } | - pallet_assets::Call::destroy_approvals { .. } | - pallet_assets::Call::finish_destroy { .. } | - pallet_assets::Call::block { .. } | - pallet_assets::Call::mint { .. } | - pallet_assets::Call::burn { .. } | - pallet_assets::Call::transfer { .. } | - pallet_assets::Call::transfer_keep_alive { .. } | - pallet_assets::Call::force_transfer { .. } | - pallet_assets::Call::freeze { .. } | - pallet_assets::Call::thaw { .. } | - pallet_assets::Call::freeze_asset { .. } | - pallet_assets::Call::thaw_asset { .. } | - pallet_assets::Call::transfer_ownership { .. } | - pallet_assets::Call::set_team { .. } | - pallet_assets::Call::set_metadata { .. } | - pallet_assets::Call::clear_metadata { .. } | - pallet_assets::Call::force_set_metadata { .. } | - pallet_assets::Call::force_clear_metadata { .. } | - pallet_assets::Call::force_asset_status { .. } | - pallet_assets::Call::approve_transfer { .. } | - pallet_assets::Call::cancel_approval { .. } | - pallet_assets::Call::force_cancel_approval { .. } | - pallet_assets::Call::transfer_approved { .. } | - pallet_assets::Call::touch { .. } | - pallet_assets::Call::touch_other { .. } | - pallet_assets::Call::refund { .. } | - pallet_assets::Call::refund_other { .. }, - ) | RuntimeCall::ForeignAssets( - pallet_assets::Call::create { .. } | - pallet_assets::Call::force_create { .. } | - pallet_assets::Call::start_destroy { .. } | - pallet_assets::Call::destroy_accounts { .. } | - pallet_assets::Call::destroy_approvals { .. } | - pallet_assets::Call::finish_destroy { .. } | - pallet_assets::Call::block { .. } | - pallet_assets::Call::mint { .. } | - pallet_assets::Call::burn { .. } | - pallet_assets::Call::transfer { .. } | - pallet_assets::Call::transfer_keep_alive { .. } | - pallet_assets::Call::force_transfer { .. } | - pallet_assets::Call::freeze { .. } | - pallet_assets::Call::thaw { .. } | - pallet_assets::Call::freeze_asset { .. } | - pallet_assets::Call::thaw_asset { .. } | - pallet_assets::Call::transfer_ownership { .. } | - pallet_assets::Call::set_team { .. } | - pallet_assets::Call::set_metadata { .. } | - pallet_assets::Call::clear_metadata { .. } | - pallet_assets::Call::force_set_metadata { .. } | - pallet_assets::Call::force_clear_metadata { .. } | - pallet_assets::Call::force_asset_status { .. } | - pallet_assets::Call::approve_transfer { .. } | - pallet_assets::Call::cancel_approval { .. } | - pallet_assets::Call::force_cancel_approval { .. } | - pallet_assets::Call::transfer_approved { .. } | - pallet_assets::Call::touch { .. } | - pallet_assets::Call::touch_other { .. } | - pallet_assets::Call::refund { .. } | - pallet_assets::Call::refund_other { .. }, - ) | RuntimeCall::PoolAssets( - pallet_assets::Call::create { .. } | - pallet_assets::Call::force_create { .. } | - pallet_assets::Call::start_destroy { .. } | - pallet_assets::Call::destroy_accounts { .. } | - pallet_assets::Call::destroy_approvals { .. } | - pallet_assets::Call::finish_destroy { .. } | - pallet_assets::Call::block { .. } | - pallet_assets::Call::mint { .. } | - pallet_assets::Call::burn { .. } | - pallet_assets::Call::transfer { .. } | - pallet_assets::Call::transfer_keep_alive { .. } | - pallet_assets::Call::force_transfer { .. } | - pallet_assets::Call::freeze { .. } | - pallet_assets::Call::thaw { .. } | - pallet_assets::Call::freeze_asset { .. } | - pallet_assets::Call::thaw_asset { .. } | - pallet_assets::Call::transfer_ownership { .. } | - pallet_assets::Call::set_team { .. } | - pallet_assets::Call::set_metadata { .. } | - pallet_assets::Call::clear_metadata { .. } | - pallet_assets::Call::force_set_metadata { .. } | - pallet_assets::Call::force_clear_metadata { .. } | - pallet_assets::Call::force_asset_status { .. } | - pallet_assets::Call::approve_transfer { .. } | - pallet_assets::Call::cancel_approval { .. } | - pallet_assets::Call::force_cancel_approval { .. } | - pallet_assets::Call::transfer_approved { .. } | - pallet_assets::Call::touch { .. } | - pallet_assets::Call::touch_other { .. } | - pallet_assets::Call::refund { .. } | - pallet_assets::Call::refund_other { .. }, - ) | RuntimeCall::AssetConversion( - pallet_asset_conversion::Call::create_pool { .. } | - pallet_asset_conversion::Call::add_liquidity { .. } | - pallet_asset_conversion::Call::remove_liquidity { .. } | - pallet_asset_conversion::Call::swap_tokens_for_exact_tokens { .. } | - pallet_asset_conversion::Call::swap_exact_tokens_for_tokens { .. }, - ) | RuntimeCall::NftFractionalization( - pallet_nft_fractionalization::Call::fractionalize { .. } | - pallet_nft_fractionalization::Call::unify { .. }, - ) | RuntimeCall::Nfts( - pallet_nfts::Call::create { .. } | - pallet_nfts::Call::force_create { .. } | - pallet_nfts::Call::destroy { .. } | - pallet_nfts::Call::mint { .. } | - pallet_nfts::Call::force_mint { .. } | - pallet_nfts::Call::burn { .. } | - pallet_nfts::Call::transfer { .. } | - pallet_nfts::Call::lock_item_transfer { .. } | - pallet_nfts::Call::unlock_item_transfer { .. } | - pallet_nfts::Call::lock_collection { .. } | - pallet_nfts::Call::transfer_ownership { .. } | - pallet_nfts::Call::set_team { .. } | - pallet_nfts::Call::force_collection_owner { .. } | - pallet_nfts::Call::force_collection_config { .. } | - pallet_nfts::Call::approve_transfer { .. } | - pallet_nfts::Call::cancel_approval { .. } | - pallet_nfts::Call::clear_all_transfer_approvals { .. } | - pallet_nfts::Call::lock_item_properties { .. } | - pallet_nfts::Call::set_attribute { .. } | - pallet_nfts::Call::force_set_attribute { .. } | - pallet_nfts::Call::clear_attribute { .. } | - pallet_nfts::Call::approve_item_attributes { .. } | - pallet_nfts::Call::cancel_item_attributes_approval { .. } | - pallet_nfts::Call::set_metadata { .. } | - pallet_nfts::Call::clear_metadata { .. } | - pallet_nfts::Call::set_collection_metadata { .. } | - pallet_nfts::Call::clear_collection_metadata { .. } | - pallet_nfts::Call::set_accept_ownership { .. } | - pallet_nfts::Call::set_collection_max_supply { .. } | - pallet_nfts::Call::update_mint_settings { .. } | - pallet_nfts::Call::set_price { .. } | - pallet_nfts::Call::buy_item { .. } | - pallet_nfts::Call::pay_tips { .. } | - pallet_nfts::Call::create_swap { .. } | - pallet_nfts::Call::cancel_swap { .. } | - pallet_nfts::Call::claim_swap { .. }, - ) | RuntimeCall::Uniques( - pallet_uniques::Call::create { .. } | - pallet_uniques::Call::force_create { .. } | - pallet_uniques::Call::destroy { .. } | - pallet_uniques::Call::mint { .. } | - pallet_uniques::Call::burn { .. } | - pallet_uniques::Call::transfer { .. } | - pallet_uniques::Call::freeze { .. } | - pallet_uniques::Call::thaw { .. } | - pallet_uniques::Call::freeze_collection { .. } | - pallet_uniques::Call::thaw_collection { .. } | - pallet_uniques::Call::transfer_ownership { .. } | - pallet_uniques::Call::set_team { .. } | - pallet_uniques::Call::approve_transfer { .. } | - pallet_uniques::Call::cancel_approval { .. } | - pallet_uniques::Call::force_item_status { .. } | - pallet_uniques::Call::set_attribute { .. } | - pallet_uniques::Call::clear_attribute { .. } | - pallet_uniques::Call::set_metadata { .. } | - pallet_uniques::Call::clear_metadata { .. } | - pallet_uniques::Call::set_collection_metadata { .. } | - pallet_uniques::Call::clear_collection_metadata { .. } | - pallet_uniques::Call::set_accept_ownership { .. } | - pallet_uniques::Call::set_collection_max_supply { .. } | - pallet_uniques::Call::set_price { .. } | - pallet_uniques::Call::buy_item { .. } - ) | RuntimeCall::ToRococoXcmRouter( - pallet_xcm_bridge_hub_router::Call::report_bridge_status { .. } - ) - ) - } -} - pub type Barrier = TrailingSetTopicAsId< DenyThenTry< DenyReserveTransferToRelayChain, From d64071eaf074df97e24fb53571c9ecd657ef25e4 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 7 May 2024 12:04:26 +0400 Subject: [PATCH 101/159] restore tempfile --- Cargo.lock | 1 + polkadot/node/core/pvf/common/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 92413d2edf6c..6b2107c0f3ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13223,6 +13223,7 @@ dependencies = [ "sp-externalities 0.25.0", "sp-io", "sp-tracing 16.0.0", + "tempfile", "thiserror", "tracing-gum", ] diff --git a/polkadot/node/core/pvf/common/Cargo.toml b/polkadot/node/core/pvf/common/Cargo.toml index bd405a4964b7..e1ce6e79cb99 100644 --- a/polkadot/node/core/pvf/common/Cargo.toml +++ b/polkadot/node/core/pvf/common/Cargo.toml @@ -42,6 +42,7 @@ seccompiler = "0.4.0" [dev-dependencies] assert_matches = "1.4.0" +tempfile = "3.3.0" [features] # This feature is used to export test code to other crates without putting it in the production build. From 819f89b0e4d39acb350c468de8c4bfdf7a250a6a Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 26 Jun 2024 14:45:19 +0300 Subject: [PATCH 102/159] taplo --- Cargo.toml | 4 ++-- umbrella/Cargo.toml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d230c5ec6a57..5158e627389c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -303,10 +303,10 @@ members = [ "substrate/frame", "substrate/frame/alliance", "substrate/frame/asset-conversion", - "substrate/frame/asset-rewards", "substrate/frame/asset-conversion/ops", "substrate/frame/asset-rate", "substrate/frame/asset-rewards", + "substrate/frame/asset-rewards", "substrate/frame/assets", "substrate/frame/assets-freezer", "substrate/frame/atomic-swap", @@ -856,10 +856,10 @@ once_cell = { version = "1.19.0" } orchestra = { version = "0.3.5", default-features = false } pallet-alliance = { path = "substrate/frame/alliance", default-features = false } pallet-asset-conversion = { path = "substrate/frame/asset-conversion", default-features = false } -pallet-asset-rewards = { path = "substrate/frame/asset-rewards", default-features = false } pallet-asset-conversion-ops = { path = "substrate/frame/asset-conversion/ops", default-features = false } pallet-asset-conversion-tx-payment = { path = "substrate/frame/transaction-payment/asset-conversion-tx-payment", default-features = false } pallet-asset-rate = { path = "substrate/frame/asset-rate", default-features = false } +pallet-asset-rewards = { path = "substrate/frame/asset-rewards", default-features = false } pallet-asset-tx-payment = { path = "substrate/frame/transaction-payment/asset-tx-payment", default-features = false } pallet-assets = { path = "substrate/frame/assets", default-features = false } pallet-assets-freezer = { path = "substrate/frame/assets-freezer", default-features = false } diff --git a/umbrella/Cargo.toml b/umbrella/Cargo.toml index b607bc913ce1..3c8cee9a3421 100644 --- a/umbrella/Cargo.toml +++ b/umbrella/Cargo.toml @@ -66,8 +66,8 @@ std = [ "pallet-asset-conversion-ops?/std", "pallet-asset-conversion-tx-payment?/std", "pallet-asset-conversion?/std", - "pallet-asset-rewards?/std", "pallet-asset-rate?/std", + "pallet-asset-rewards?/std", "pallet-asset-tx-payment?/std", "pallet-assets-freezer?/std", "pallet-assets?/std", @@ -264,6 +264,7 @@ runtime-benchmarks = [ "pallet-asset-conversion-ops?/runtime-benchmarks", "pallet-asset-conversion?/runtime-benchmarks", "pallet-asset-rate?/runtime-benchmarks", + "pallet-asset-rewards?/runtime-benchmarks", "pallet-asset-tx-payment?/runtime-benchmarks", "pallet-assets-freezer?/runtime-benchmarks", "pallet-assets?/runtime-benchmarks", @@ -367,7 +368,6 @@ runtime-benchmarks = [ "staging-xcm-builder?/runtime-benchmarks", "staging-xcm-executor?/runtime-benchmarks", "xcm-fee-payment-runtime-api?/runtime-benchmarks", - "pallet-asset-rewards?/runtime-benchmarks" ] try-runtime = [ "cumulus-pallet-aura-ext?/try-runtime", @@ -388,6 +388,7 @@ try-runtime = [ "pallet-asset-conversion-tx-payment?/try-runtime", "pallet-asset-conversion?/try-runtime", "pallet-asset-rate?/try-runtime", + "pallet-asset-rewards?/try-runtime", "pallet-asset-tx-payment?/try-runtime", "pallet-assets-freezer?/try-runtime", "pallet-assets?/try-runtime", @@ -483,7 +484,6 @@ try-runtime = [ "snowbridge-pallet-system?/try-runtime", "sp-runtime?/try-runtime", "staging-parachain-info?/try-runtime", - "pallet-asset-rewards?/try-runtime" ] serde = [ "bp-polkadot-core?/serde", @@ -542,7 +542,7 @@ with-tracing = [ "sp-tracing?/with-tracing", "sp-tracing?/with-tracing", ] -runtime = ["assets-common", "binary-merkle-tree", "bp-asset-hub-rococo", "bp-asset-hub-westend", "bp-bridge-hub-cumulus", "bp-bridge-hub-kusama", "bp-bridge-hub-polkadot", "bp-bridge-hub-rococo", "bp-bridge-hub-westend", "bp-header-chain", "bp-kusama", "bp-messages", "bp-parachains", "bp-polkadot", "bp-polkadot-bulletin", "bp-polkadot-core", "bp-relayers", "bp-rococo", "bp-runtime", "bp-test-utils", "bp-westend", "bp-xcm-bridge-hub", "bp-xcm-bridge-hub-router", "bridge-hub-common", "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", "cumulus-pallet-parachain-system-proc-macro", "cumulus-pallet-session-benchmarking", "cumulus-pallet-solo-to-para", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-ping", "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-primitives-proof-size-hostfunction", "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-timestamp", "cumulus-primitives-utility", "frame-benchmarking", "frame-benchmarking-pallet-pov", "frame-election-provider-solution-type", "frame-election-provider-support", "frame-executive", "frame-metadata-hash-extension", "frame-support", "frame-support-procedural", "frame-support-procedural-tools-derive", "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", "pallet-alliance", "pallet-asset-conversion", "pallet-asset-rewards", "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", "pallet-asset-tx-payment", "pallet-assets", "pallet-assets-freezer", "pallet-atomic-swap", "pallet-aura", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", "pallet-bags-list", "pallet-balances", "pallet-beefy", "pallet-beefy-mmr", "pallet-bounties", "pallet-bridge-grandpa", "pallet-bridge-messages", "pallet-bridge-parachains", "pallet-bridge-relayers", "pallet-broker", "pallet-child-bounties", "pallet-collator-selection", "pallet-collective", "pallet-collective-content", "pallet-contracts", "pallet-contracts-proc-macro", "pallet-contracts-uapi", "pallet-conviction-voting", "pallet-core-fellowship", "pallet-delegated-staking", "pallet-democracy", "pallet-dev-mode", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", "pallet-fast-unstake", "pallet-glutton", "pallet-grandpa", "pallet-identity", "pallet-im-online", "pallet-indices", "pallet-insecure-randomness-collective-flip", "pallet-lottery", "pallet-membership", "pallet-message-queue", "pallet-migrations", "pallet-mixnet", "pallet-mmr", "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-nis", "pallet-node-authorization", "pallet-nomination-pools", "pallet-nomination-pools-benchmarking", "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", "pallet-paged-list", "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", "pallet-recovery", "pallet-referenda", "pallet-remark", "pallet-root-offences", "pallet-root-testing", "pallet-safe-mode", "pallet-salary", "pallet-scheduler", "pallet-scored-pool", "pallet-session", "pallet-session-benchmarking", "pallet-skip-feeless-payment", "pallet-society", "pallet-staking", "pallet-staking-reward-curve", "pallet-staking-reward-fn", "pallet-staking-runtime-api", "pallet-state-trie-migration", "pallet-statement", "pallet-sudo", "pallet-timestamp", "pallet-tips", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", "pallet-tx-pause", "pallet-uniques", "pallet-utility", "pallet-vesting", "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-bridge-hub", "pallet-xcm-bridge-hub-router", "parachains-common", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-metrics", "polkadot-runtime-parachains", "polkadot-sdk-frame", "rococo-runtime-constants", "sc-chain-spec-derive", "sc-tracing-proc-macro", "slot-range-helper", "snowbridge-beacon-primitives", "snowbridge-core", "snowbridge-ethereum", "snowbridge-outbound-queue-merkle-tree", "snowbridge-outbound-queue-runtime-api", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-ethereum-client-fixtures", "snowbridge-pallet-inbound-queue", "snowbridge-pallet-inbound-queue-fixtures", "snowbridge-pallet-outbound-queue", "snowbridge-pallet-system", "snowbridge-router-primitives", "snowbridge-runtime-common", "snowbridge-system-runtime-api", "sp-api", "sp-api-proc-macro", "sp-application-crypto", "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", "sp-consensus-pow", "sp-consensus-slots", "sp-core", "sp-crypto-ec-utils", "sp-crypto-hashing", "sp-crypto-hashing-proc-macro", "sp-debug-derive", "sp-externalities", "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keyring", "sp-keystore", "sp-metadata-ir", "sp-mixnet", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", "sp-runtime", "sp-runtime-interface", "sp-runtime-interface-proc-macro", "sp-session", "sp-staking", "sp-state-machine", "sp-statement-store", "sp-std", "sp-storage", "sp-timestamp", "sp-tracing", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", "sp-version", "sp-version-proc-macro", "sp-wasm-interface", "sp-weights", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", "substrate-bip39", "testnet-parachains-constants", "tracing-gum-proc-macro", "westend-runtime-constants", "xcm-fee-payment-runtime-api", "xcm-procedural"] +runtime = ["assets-common", "binary-merkle-tree", "bp-asset-hub-rococo", "bp-asset-hub-westend", "bp-bridge-hub-cumulus", "bp-bridge-hub-kusama", "bp-bridge-hub-polkadot", "bp-bridge-hub-rococo", "bp-bridge-hub-westend", "bp-header-chain", "bp-kusama", "bp-messages", "bp-parachains", "bp-polkadot", "bp-polkadot-bulletin", "bp-polkadot-core", "bp-relayers", "bp-rococo", "bp-runtime", "bp-test-utils", "bp-westend", "bp-xcm-bridge-hub", "bp-xcm-bridge-hub-router", "bridge-hub-common", "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", "cumulus-pallet-parachain-system-proc-macro", "cumulus-pallet-session-benchmarking", "cumulus-pallet-solo-to-para", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-ping", "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-primitives-proof-size-hostfunction", "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-timestamp", "cumulus-primitives-utility", "frame-benchmarking", "frame-benchmarking-pallet-pov", "frame-election-provider-solution-type", "frame-election-provider-support", "frame-executive", "frame-metadata-hash-extension", "frame-support", "frame-support-procedural", "frame-support-procedural-tools-derive", "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", "pallet-alliance", "pallet-asset-conversion", "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", "pallet-asset-rewards", "pallet-asset-tx-payment", "pallet-assets", "pallet-assets-freezer", "pallet-atomic-swap", "pallet-aura", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", "pallet-bags-list", "pallet-balances", "pallet-beefy", "pallet-beefy-mmr", "pallet-bounties", "pallet-bridge-grandpa", "pallet-bridge-messages", "pallet-bridge-parachains", "pallet-bridge-relayers", "pallet-broker", "pallet-child-bounties", "pallet-collator-selection", "pallet-collective", "pallet-collective-content", "pallet-contracts", "pallet-contracts-proc-macro", "pallet-contracts-uapi", "pallet-conviction-voting", "pallet-core-fellowship", "pallet-delegated-staking", "pallet-democracy", "pallet-dev-mode", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", "pallet-fast-unstake", "pallet-glutton", "pallet-grandpa", "pallet-identity", "pallet-im-online", "pallet-indices", "pallet-insecure-randomness-collective-flip", "pallet-lottery", "pallet-membership", "pallet-message-queue", "pallet-migrations", "pallet-mixnet", "pallet-mmr", "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-nis", "pallet-node-authorization", "pallet-nomination-pools", "pallet-nomination-pools-benchmarking", "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", "pallet-paged-list", "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", "pallet-recovery", "pallet-referenda", "pallet-remark", "pallet-root-offences", "pallet-root-testing", "pallet-safe-mode", "pallet-salary", "pallet-scheduler", "pallet-scored-pool", "pallet-session", "pallet-session-benchmarking", "pallet-skip-feeless-payment", "pallet-society", "pallet-staking", "pallet-staking-reward-curve", "pallet-staking-reward-fn", "pallet-staking-runtime-api", "pallet-state-trie-migration", "pallet-statement", "pallet-sudo", "pallet-timestamp", "pallet-tips", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", "pallet-tx-pause", "pallet-uniques", "pallet-utility", "pallet-vesting", "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-bridge-hub", "pallet-xcm-bridge-hub-router", "parachains-common", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-metrics", "polkadot-runtime-parachains", "polkadot-sdk-frame", "rococo-runtime-constants", "sc-chain-spec-derive", "sc-tracing-proc-macro", "slot-range-helper", "snowbridge-beacon-primitives", "snowbridge-core", "snowbridge-ethereum", "snowbridge-outbound-queue-merkle-tree", "snowbridge-outbound-queue-runtime-api", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-ethereum-client-fixtures", "snowbridge-pallet-inbound-queue", "snowbridge-pallet-inbound-queue-fixtures", "snowbridge-pallet-outbound-queue", "snowbridge-pallet-system", "snowbridge-router-primitives", "snowbridge-runtime-common", "snowbridge-system-runtime-api", "sp-api", "sp-api-proc-macro", "sp-application-crypto", "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", "sp-consensus-pow", "sp-consensus-slots", "sp-core", "sp-crypto-ec-utils", "sp-crypto-hashing", "sp-crypto-hashing-proc-macro", "sp-debug-derive", "sp-externalities", "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keyring", "sp-keystore", "sp-metadata-ir", "sp-mixnet", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", "sp-runtime", "sp-runtime-interface", "sp-runtime-interface-proc-macro", "sp-session", "sp-staking", "sp-state-machine", "sp-statement-store", "sp-std", "sp-storage", "sp-timestamp", "sp-tracing", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", "sp-version", "sp-version-proc-macro", "sp-wasm-interface", "sp-weights", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", "substrate-bip39", "testnet-parachains-constants", "tracing-gum-proc-macro", "westend-runtime-constants", "xcm-fee-payment-runtime-api", "xcm-procedural"] node = ["asset-test-utils", "bridge-hub-test-utils", "cumulus-client-cli", "cumulus-client-collator", "cumulus-client-consensus-aura", "cumulus-client-consensus-common", "cumulus-client-consensus-proposer", "cumulus-client-consensus-relay-chain", "cumulus-client-network", "cumulus-client-parachain-inherent", "cumulus-client-pov-recovery", "cumulus-client-service", "cumulus-relay-chain-inprocess-interface", "cumulus-relay-chain-interface", "cumulus-relay-chain-minimal-node", "cumulus-relay-chain-rpc-interface", "cumulus-test-relay-sproof-builder", "emulated-integration-tests-common", "fork-tree", "frame-benchmarking-cli", "frame-remote-externalities", "frame-support-procedural-tools", "generate-bags", "mmr-gadget", "mmr-rpc", "pallet-contracts-mock-network", "pallet-transaction-payment-rpc", "parachains-runtimes-test-utils", "polkadot-approval-distribution", "polkadot-availability-bitfield-distribution", "polkadot-availability-distribution", "polkadot-availability-recovery", "polkadot-cli", "polkadot-collator-protocol", "polkadot-dispute-distribution", "polkadot-erasure-coding", "polkadot-gossip-support", "polkadot-network-bridge", "polkadot-node-collation-generation", "polkadot-node-core-approval-voting", "polkadot-node-core-av-store", "polkadot-node-core-backing", "polkadot-node-core-bitfield-signing", "polkadot-node-core-candidate-validation", "polkadot-node-core-chain-api", "polkadot-node-core-chain-selection", "polkadot-node-core-dispute-coordinator", "polkadot-node-core-parachains-inherent", "polkadot-node-core-prospective-parachains", "polkadot-node-core-provisioner", "polkadot-node-core-pvf", "polkadot-node-core-pvf-checker", "polkadot-node-core-pvf-common", "polkadot-node-core-pvf-execute-worker", "polkadot-node-core-pvf-prepare-worker", "polkadot-node-core-runtime-api", "polkadot-node-jaeger", "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-types", "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-rpc", "polkadot-service", "polkadot-statement-distribution", "polkadot-statement-table", "sc-allocator", "sc-authority-discovery", "sc-basic-authorship", "sc-block-builder", "sc-chain-spec", "sc-cli", "sc-client-api", "sc-client-db", "sc-consensus", "sc-consensus-aura", "sc-consensus-babe", "sc-consensus-babe-rpc", "sc-consensus-beefy", "sc-consensus-beefy-rpc", "sc-consensus-epochs", "sc-consensus-grandpa", "sc-consensus-grandpa-rpc", "sc-consensus-manual-seal", "sc-consensus-pow", "sc-consensus-slots", "sc-executor", "sc-executor-common", "sc-executor-polkavm", "sc-executor-wasmtime", "sc-informant", "sc-keystore", "sc-mixnet", "sc-network", "sc-network-common", "sc-network-gossip", "sc-network-light", "sc-network-statement", "sc-network-sync", "sc-network-transactions", "sc-network-types", "sc-offchain", "sc-proposer-metrics", "sc-rpc", "sc-rpc-api", "sc-rpc-server", "sc-rpc-spec-v2", "sc-service", "sc-state-db", "sc-statement-store", "sc-storage-monitor", "sc-sync-state-rpc", "sc-sysinfo", "sc-telemetry", "sc-tracing", "sc-transaction-pool", "sc-transaction-pool-api", "sc-utils", "snowbridge-runtime-test-common", "sp-blockchain", "sp-consensus", "sp-core-hashing", "sp-core-hashing-proc-macro", "sp-database", "sp-maybe-compressed-blob", "sp-panic-handler", "sp-rpc", "staging-chain-spec-builder", "staging-node-inspect", "staging-tracking-allocator", "std", "subkey", "substrate-build-script-utils", "substrate-frame-rpc-support", "substrate-frame-rpc-system", "substrate-prometheus-endpoint", "substrate-rpc-client", "substrate-state-trie-migration-rpc", "substrate-wasm-builder", "tracing-gum", "xcm-emulator", "xcm-simulator"] tuples-96 = [ "frame-support-procedural?/tuples-96", From 6d5554fb5a8b699d6608a020443f375a815d033f Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Wed, 26 Jun 2024 15:17:18 +0300 Subject: [PATCH 103/159] apply umbrella patch --- umbrella/Cargo.toml | 12 ++++++------ umbrella/src/lib.rs | 4 ++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/umbrella/Cargo.toml b/umbrella/Cargo.toml index 3c8cee9a3421..28f9ef1d2d19 100644 --- a/umbrella/Cargo.toml +++ b/umbrella/Cargo.toml @@ -542,7 +542,7 @@ with-tracing = [ "sp-tracing?/with-tracing", "sp-tracing?/with-tracing", ] -runtime = ["assets-common", "binary-merkle-tree", "bp-asset-hub-rococo", "bp-asset-hub-westend", "bp-bridge-hub-cumulus", "bp-bridge-hub-kusama", "bp-bridge-hub-polkadot", "bp-bridge-hub-rococo", "bp-bridge-hub-westend", "bp-header-chain", "bp-kusama", "bp-messages", "bp-parachains", "bp-polkadot", "bp-polkadot-bulletin", "bp-polkadot-core", "bp-relayers", "bp-rococo", "bp-runtime", "bp-test-utils", "bp-westend", "bp-xcm-bridge-hub", "bp-xcm-bridge-hub-router", "bridge-hub-common", "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", "cumulus-pallet-parachain-system-proc-macro", "cumulus-pallet-session-benchmarking", "cumulus-pallet-solo-to-para", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-ping", "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-primitives-proof-size-hostfunction", "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-timestamp", "cumulus-primitives-utility", "frame-benchmarking", "frame-benchmarking-pallet-pov", "frame-election-provider-solution-type", "frame-election-provider-support", "frame-executive", "frame-metadata-hash-extension", "frame-support", "frame-support-procedural", "frame-support-procedural-tools-derive", "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", "pallet-alliance", "pallet-asset-conversion", "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", "pallet-asset-rewards", "pallet-asset-tx-payment", "pallet-assets", "pallet-assets-freezer", "pallet-atomic-swap", "pallet-aura", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", "pallet-bags-list", "pallet-balances", "pallet-beefy", "pallet-beefy-mmr", "pallet-bounties", "pallet-bridge-grandpa", "pallet-bridge-messages", "pallet-bridge-parachains", "pallet-bridge-relayers", "pallet-broker", "pallet-child-bounties", "pallet-collator-selection", "pallet-collective", "pallet-collective-content", "pallet-contracts", "pallet-contracts-proc-macro", "pallet-contracts-uapi", "pallet-conviction-voting", "pallet-core-fellowship", "pallet-delegated-staking", "pallet-democracy", "pallet-dev-mode", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", "pallet-fast-unstake", "pallet-glutton", "pallet-grandpa", "pallet-identity", "pallet-im-online", "pallet-indices", "pallet-insecure-randomness-collective-flip", "pallet-lottery", "pallet-membership", "pallet-message-queue", "pallet-migrations", "pallet-mixnet", "pallet-mmr", "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-nis", "pallet-node-authorization", "pallet-nomination-pools", "pallet-nomination-pools-benchmarking", "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", "pallet-paged-list", "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", "pallet-recovery", "pallet-referenda", "pallet-remark", "pallet-root-offences", "pallet-root-testing", "pallet-safe-mode", "pallet-salary", "pallet-scheduler", "pallet-scored-pool", "pallet-session", "pallet-session-benchmarking", "pallet-skip-feeless-payment", "pallet-society", "pallet-staking", "pallet-staking-reward-curve", "pallet-staking-reward-fn", "pallet-staking-runtime-api", "pallet-state-trie-migration", "pallet-statement", "pallet-sudo", "pallet-timestamp", "pallet-tips", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", "pallet-tx-pause", "pallet-uniques", "pallet-utility", "pallet-vesting", "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-bridge-hub", "pallet-xcm-bridge-hub-router", "parachains-common", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-metrics", "polkadot-runtime-parachains", "polkadot-sdk-frame", "rococo-runtime-constants", "sc-chain-spec-derive", "sc-tracing-proc-macro", "slot-range-helper", "snowbridge-beacon-primitives", "snowbridge-core", "snowbridge-ethereum", "snowbridge-outbound-queue-merkle-tree", "snowbridge-outbound-queue-runtime-api", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-ethereum-client-fixtures", "snowbridge-pallet-inbound-queue", "snowbridge-pallet-inbound-queue-fixtures", "snowbridge-pallet-outbound-queue", "snowbridge-pallet-system", "snowbridge-router-primitives", "snowbridge-runtime-common", "snowbridge-system-runtime-api", "sp-api", "sp-api-proc-macro", "sp-application-crypto", "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", "sp-consensus-pow", "sp-consensus-slots", "sp-core", "sp-crypto-ec-utils", "sp-crypto-hashing", "sp-crypto-hashing-proc-macro", "sp-debug-derive", "sp-externalities", "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keyring", "sp-keystore", "sp-metadata-ir", "sp-mixnet", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", "sp-runtime", "sp-runtime-interface", "sp-runtime-interface-proc-macro", "sp-session", "sp-staking", "sp-state-machine", "sp-statement-store", "sp-std", "sp-storage", "sp-timestamp", "sp-tracing", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", "sp-version", "sp-version-proc-macro", "sp-wasm-interface", "sp-weights", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", "substrate-bip39", "testnet-parachains-constants", "tracing-gum-proc-macro", "westend-runtime-constants", "xcm-fee-payment-runtime-api", "xcm-procedural"] +runtime = ["assets-common", "binary-merkle-tree", "bp-asset-hub-rococo", "bp-asset-hub-westend", "bp-bridge-hub-cumulus", "bp-bridge-hub-kusama", "bp-bridge-hub-polkadot", "bp-bridge-hub-rococo", "bp-bridge-hub-westend", "bp-header-chain", "bp-kusama", "bp-messages", "bp-parachains", "bp-polkadot", "bp-polkadot-bulletin", "bp-polkadot-core", "bp-relayers", "bp-rococo", "bp-runtime", "bp-test-utils", "bp-westend", "bp-xcm-bridge-hub", "bp-xcm-bridge-hub-router", "bridge-hub-common", "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", "cumulus-pallet-parachain-system-proc-macro", "cumulus-pallet-session-benchmarking", "cumulus-pallet-solo-to-para", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-ping", "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-primitives-proof-size-hostfunction", "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-timestamp", "cumulus-primitives-utility", "frame-benchmarking", "frame-benchmarking-pallet-pov", "frame-election-provider-solution-type", "frame-election-provider-support", "frame-executive", "frame-metadata-hash-extension", "frame-support", "frame-support-procedural", "frame-support-procedural-tools-derive", "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", "pallet-alliance", "pallet-asset-conversion", "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", "pallet-asset-rewards", "pallet-asset-rewards", "pallet-asset-tx-payment", "pallet-assets", "pallet-assets-freezer", "pallet-atomic-swap", "pallet-aura", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", "pallet-bags-list", "pallet-balances", "pallet-beefy", "pallet-beefy-mmr", "pallet-bounties", "pallet-bridge-grandpa", "pallet-bridge-messages", "pallet-bridge-parachains", "pallet-bridge-relayers", "pallet-broker", "pallet-child-bounties", "pallet-collator-selection", "pallet-collective", "pallet-collective-content", "pallet-contracts", "pallet-contracts-proc-macro", "pallet-contracts-uapi", "pallet-conviction-voting", "pallet-core-fellowship", "pallet-delegated-staking", "pallet-democracy", "pallet-dev-mode", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", "pallet-fast-unstake", "pallet-glutton", "pallet-grandpa", "pallet-identity", "pallet-im-online", "pallet-indices", "pallet-insecure-randomness-collective-flip", "pallet-lottery", "pallet-membership", "pallet-message-queue", "pallet-migrations", "pallet-mixnet", "pallet-mmr", "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-nis", "pallet-node-authorization", "pallet-nomination-pools", "pallet-nomination-pools-benchmarking", "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", "pallet-paged-list", "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", "pallet-recovery", "pallet-referenda", "pallet-remark", "pallet-root-offences", "pallet-root-testing", "pallet-safe-mode", "pallet-salary", "pallet-scheduler", "pallet-scored-pool", "pallet-session", "pallet-session-benchmarking", "pallet-skip-feeless-payment", "pallet-society", "pallet-staking", "pallet-staking-reward-curve", "pallet-staking-reward-fn", "pallet-staking-runtime-api", "pallet-state-trie-migration", "pallet-statement", "pallet-sudo", "pallet-timestamp", "pallet-tips", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", "pallet-tx-pause", "pallet-uniques", "pallet-utility", "pallet-vesting", "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-bridge-hub", "pallet-xcm-bridge-hub-router", "parachains-common", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-metrics", "polkadot-runtime-parachains", "polkadot-sdk-frame", "rococo-runtime-constants", "sc-chain-spec-derive", "sc-tracing-proc-macro", "slot-range-helper", "snowbridge-beacon-primitives", "snowbridge-core", "snowbridge-ethereum", "snowbridge-outbound-queue-merkle-tree", "snowbridge-outbound-queue-runtime-api", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-ethereum-client-fixtures", "snowbridge-pallet-inbound-queue", "snowbridge-pallet-inbound-queue-fixtures", "snowbridge-pallet-outbound-queue", "snowbridge-pallet-system", "snowbridge-router-primitives", "snowbridge-runtime-common", "snowbridge-system-runtime-api", "sp-api", "sp-api-proc-macro", "sp-application-crypto", "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", "sp-consensus-pow", "sp-consensus-slots", "sp-core", "sp-crypto-ec-utils", "sp-crypto-hashing", "sp-crypto-hashing-proc-macro", "sp-debug-derive", "sp-externalities", "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keyring", "sp-keystore", "sp-metadata-ir", "sp-mixnet", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", "sp-runtime", "sp-runtime-interface", "sp-runtime-interface-proc-macro", "sp-session", "sp-staking", "sp-state-machine", "sp-statement-store", "sp-std", "sp-storage", "sp-timestamp", "sp-tracing", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", "sp-version", "sp-version-proc-macro", "sp-wasm-interface", "sp-weights", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", "substrate-bip39", "testnet-parachains-constants", "tracing-gum-proc-macro", "westend-runtime-constants", "xcm-fee-payment-runtime-api", "xcm-procedural"] node = ["asset-test-utils", "bridge-hub-test-utils", "cumulus-client-cli", "cumulus-client-collator", "cumulus-client-consensus-aura", "cumulus-client-consensus-common", "cumulus-client-consensus-proposer", "cumulus-client-consensus-relay-chain", "cumulus-client-network", "cumulus-client-parachain-inherent", "cumulus-client-pov-recovery", "cumulus-client-service", "cumulus-relay-chain-inprocess-interface", "cumulus-relay-chain-interface", "cumulus-relay-chain-minimal-node", "cumulus-relay-chain-rpc-interface", "cumulus-test-relay-sproof-builder", "emulated-integration-tests-common", "fork-tree", "frame-benchmarking-cli", "frame-remote-externalities", "frame-support-procedural-tools", "generate-bags", "mmr-gadget", "mmr-rpc", "pallet-contracts-mock-network", "pallet-transaction-payment-rpc", "parachains-runtimes-test-utils", "polkadot-approval-distribution", "polkadot-availability-bitfield-distribution", "polkadot-availability-distribution", "polkadot-availability-recovery", "polkadot-cli", "polkadot-collator-protocol", "polkadot-dispute-distribution", "polkadot-erasure-coding", "polkadot-gossip-support", "polkadot-network-bridge", "polkadot-node-collation-generation", "polkadot-node-core-approval-voting", "polkadot-node-core-av-store", "polkadot-node-core-backing", "polkadot-node-core-bitfield-signing", "polkadot-node-core-candidate-validation", "polkadot-node-core-chain-api", "polkadot-node-core-chain-selection", "polkadot-node-core-dispute-coordinator", "polkadot-node-core-parachains-inherent", "polkadot-node-core-prospective-parachains", "polkadot-node-core-provisioner", "polkadot-node-core-pvf", "polkadot-node-core-pvf-checker", "polkadot-node-core-pvf-common", "polkadot-node-core-pvf-execute-worker", "polkadot-node-core-pvf-prepare-worker", "polkadot-node-core-runtime-api", "polkadot-node-jaeger", "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-types", "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-rpc", "polkadot-service", "polkadot-statement-distribution", "polkadot-statement-table", "sc-allocator", "sc-authority-discovery", "sc-basic-authorship", "sc-block-builder", "sc-chain-spec", "sc-cli", "sc-client-api", "sc-client-db", "sc-consensus", "sc-consensus-aura", "sc-consensus-babe", "sc-consensus-babe-rpc", "sc-consensus-beefy", "sc-consensus-beefy-rpc", "sc-consensus-epochs", "sc-consensus-grandpa", "sc-consensus-grandpa-rpc", "sc-consensus-manual-seal", "sc-consensus-pow", "sc-consensus-slots", "sc-executor", "sc-executor-common", "sc-executor-polkavm", "sc-executor-wasmtime", "sc-informant", "sc-keystore", "sc-mixnet", "sc-network", "sc-network-common", "sc-network-gossip", "sc-network-light", "sc-network-statement", "sc-network-sync", "sc-network-transactions", "sc-network-types", "sc-offchain", "sc-proposer-metrics", "sc-rpc", "sc-rpc-api", "sc-rpc-server", "sc-rpc-spec-v2", "sc-service", "sc-state-db", "sc-statement-store", "sc-storage-monitor", "sc-sync-state-rpc", "sc-sysinfo", "sc-telemetry", "sc-tracing", "sc-transaction-pool", "sc-transaction-pool-api", "sc-utils", "snowbridge-runtime-test-common", "sp-blockchain", "sp-consensus", "sp-core-hashing", "sp-core-hashing-proc-macro", "sp-database", "sp-maybe-compressed-blob", "sp-panic-handler", "sp-rpc", "staging-chain-spec-builder", "staging-node-inspect", "staging-tracking-allocator", "std", "subkey", "substrate-build-script-utils", "substrate-frame-rpc-support", "substrate-frame-rpc-system", "substrate-prometheus-endpoint", "substrate-rpc-client", "substrate-state-trie-migration-rpc", "substrate-wasm-builder", "tracing-gum", "xcm-emulator", "xcm-simulator"] tuples-96 = [ "frame-support-procedural?/tuples-96", @@ -835,11 +835,6 @@ path = "../substrate/frame/asset-conversion" default-features = false optional = true -[dependencies.pallet-asset-rewards] -path = "../substrate/frame/asset-rewards" -default-features = false -optional = true - [dependencies.pallet-asset-conversion-ops] path = "../substrate/frame/asset-conversion/ops" default-features = false @@ -855,6 +850,11 @@ path = "../substrate/frame/asset-rate" default-features = false optional = true +[dependencies.pallet-asset-rewards] +path = "../substrate/frame/asset-rewards" +default-features = false +optional = true + [dependencies.pallet-asset-tx-payment] path = "../substrate/frame/transaction-payment/asset-tx-payment" default-features = false diff --git a/umbrella/src/lib.rs b/umbrella/src/lib.rs index 87fcd4214dbc..7f1016672fcc 100644 --- a/umbrella/src/lib.rs +++ b/umbrella/src/lib.rs @@ -340,6 +340,10 @@ pub use pallet_alliance; #[cfg(feature = "pallet-asset-conversion")] pub use pallet_asset_conversion; +/// FRAME asset conversion pallet. +#[cfg(feature = "pallet-asset-rewards")] +pub use pallet_asset_rewards; + /// FRAME asset conversion pallet's operations suite. #[cfg(feature = "pallet-asset-conversion-ops")] pub use pallet_asset_conversion_ops; From de5577e34775c23a73007632341581af6241ea35 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Mon, 1 Jul 2024 20:13:09 +0200 Subject: [PATCH 104/159] add freezing --- Cargo.lock | 1 + .../assets/asset-hub-rococo/src/lib.rs | 43 +++++++++++++- .../assets/asset-hub-westend/src/lib.rs | 45 +++++++++++++- substrate/bin/node/runtime/src/lib.rs | 14 +++++ substrate/frame/asset-rewards/Cargo.toml | 1 + substrate/frame/asset-rewards/src/lib.rs | 57 +++++++++++++++++- substrate/frame/asset-rewards/src/mock.rs | 23 ++++++-- substrate/frame/asset-rewards/src/tests.rs | 58 +++++++++++++++++-- 8 files changed, 223 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f835b47db2e9..d1e267eab384 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9775,6 +9775,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-assets", + "pallet-assets-freezer", "pallet-balances", "parity-scale-codec", "primitive-types", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 106b5ecdfbd8..fc3e5b63cf9e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -211,8 +211,8 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; - type FreezeIdentifier = (); - type MaxFreezes = ConstU32<0>; + type FreezeIdentifier = RuntimeFreezeReason; + type MaxFreezes = ConstU32<50>; } parameter_types! { @@ -335,6 +335,19 @@ pub type LocalAndForeignAssets = fungibles::UnionOf< AccountId, >; +/// Union fungibles implementation for `AssetsFreezer` and `ForeignAssetsFreezer`. +pub type LocalAndForeignAssetsFreezer = fungibles::UnionOf< + AssetsFreezer, + ForeignAssetsFreezer, + LocalFromLeft< + AssetIdForTrustBackedAssetsConvert, + AssetIdForTrustBackedAssets, + xcm::v3::Location, + >, + xcm::v3::Location, + AccountId, +>; + /// Union fungibles implementation for [`LocalAndForeignAssets`] and [`Balances`]. pub type NativeAndNonPoolAssets = fungible::UnionOf< Balances, @@ -344,6 +357,15 @@ pub type NativeAndNonPoolAssets = fungible::UnionOf< AccountId, >; +/// Union fungibles implementation for [`LocalAndForeignAssetsFreezer`] and [`Balances`]. +pub type NativeAndNonPoolAssetsFreezer = fungible::UnionOf< + Balances, + LocalAndForeignAssetsFreezer, + TargetFromLeft, + xcm::v3::Location, + AccountId, +>; + /// Union fungibles implementation for [`PoolAssets`] and [`NativeAndNonPoolAssets`]. /// /// NOTE: Should be kept updated to include ALL balances and assets in the runtime. @@ -359,6 +381,21 @@ pub type NativeAndAllAssets = fungibles::UnionOf< AccountId, >; +/// Union fungibles implementation for [`PoolAssetsFreezer`] and [`NativeAndNonPoolAssetsFreezer`]. +/// +/// NOTE: Should be kept updated to include ALL balances and assets in the runtime. +pub type NativeAndAllAssetsFreezer = fungibles::UnionOf< + PoolAssetsFreezer, + NativeAndNonPoolAssetsFreezer, + LocalFromLeft< + AssetIdForPoolAssetsConvert, + AssetIdForPoolAssets, + xcm::v3::Location, + >, + xcm::v3::Location, + AccountId, +>; + pub type PoolIdToAccountId = pallet_asset_conversion::AccountIdConverter< AssetConversionPalletId, (xcm::v3::Location, xcm::v3::Location), @@ -980,6 +1017,7 @@ impl pallet_asset_rewards::Config for Runtime { type PalletId = AssetRewardsPalletId; type Balance = Balance; type Assets = NativeAndAllAssets; + type AssetsFreezer = NativeAndAllAssetsFreezer; type AssetId = xcm::v3::Location; type CreatePoolOrigin = EnsureWithSuccess< EitherOfDiverse< @@ -989,6 +1027,7 @@ impl pallet_asset_rewards::Config for Runtime { AccountId, TreasurerBodyAccount, >; + type RuntimeFreezeReason = RuntimeFreezeReason; type WeightInfo = weights::pallet_asset_rewards::WeightInfo; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = PalletAssetRewardsBenchmarkHelper; 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 58975eda8754..bfadc6f2f831 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -43,7 +43,7 @@ use frame_support::{ fungible, fungibles, tokens::{imbalance::ResolveAssetTo, nonfungibles_v2::Inspect}, AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, EitherOfDiverse, - Equals, InstanceFilter, TransformOrigin, + Equals, InstanceFilter, PalletInfoAccess, TransformOrigin, }, weights::{ConstantMultiplier, Weight, WeightToFee as _}, BoundedVec, PalletId, @@ -208,8 +208,8 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; - type FreezeIdentifier = (); - type MaxFreezes = ConstU32<0>; + type FreezeIdentifier = RuntimeFreezeReason; + type MaxFreezes = ConstU32<50>; } parameter_types! { @@ -330,6 +330,19 @@ pub type LocalAndForeignAssets = fungibles::UnionOf< AccountId, >; +/// Union fungibles implementation for `AssetsFreezer` and `ForeignAssetsFreezer`. +pub type LocalAndForeignAssetsFreezer = fungibles::UnionOf< + AssetsFreezer, + ForeignAssetsFreezer, + LocalFromLeft< + AssetIdForTrustBackedAssetsConvert, + AssetIdForTrustBackedAssets, + xcm::v3::Location, + >, + xcm::v3::Location, + AccountId, +>; + /// Union fungibles implementation for [`LocalAndForeignAssets`] and `Balances`. pub type NativeAndNonPoolAssets = fungible::UnionOf< Balances, @@ -339,6 +352,15 @@ pub type NativeAndNonPoolAssets = fungible::UnionOf< AccountId, >; +/// Union fungibles implementation for [`LocalAndForeignAssetsFreezer`] and [`Balances`]. +pub type NativeAndNonPoolAssetsFreezer = fungible::UnionOf< + Balances, + LocalAndForeignAssetsFreezer, + TargetFromLeft, + xcm::v3::Location, + AccountId, +>; + /// Union fungibles implementation for [`PoolAssets`] and [`NativeAndNonPoolAssets`]. /// /// NOTE: Should be kept updated to include ALL balances and assets in the runtime. @@ -354,6 +376,21 @@ pub type NativeAndAllAssets = fungibles::UnionOf< AccountId, >; +/// Union fungibles implementation for [`PoolAssetsFreezer`] and [`NativeAndNonPoolAssetsFreezer`]. +/// +/// NOTE: Should be kept updated to include ALL balances and assets in the runtime. +pub type NativeAndAllAssetsFreezer = fungibles::UnionOf< + PoolAssetsFreezer, + NativeAndNonPoolAssetsFreezer, + LocalFromLeft< + AssetIdForPoolAssetsConvert, + AssetIdForPoolAssets, + xcm::v3::Location, + >, + xcm::v3::Location, + AccountId, +>; + pub type PoolIdToAccountId = pallet_asset_conversion::AccountIdConverter< AssetConversionPalletId, (xcm::v3::Location, xcm::v3::Location), @@ -422,6 +459,7 @@ impl pallet_asset_rewards::Config for Runtime { type PalletId = AssetRewardsPalletId; type Balance = Balance; type Assets = NativeAndAllAssets; + type AssetsFreezer = NativeAndAllAssetsFreezer; type AssetId = xcm::v3::Location; type CreatePoolOrigin = EnsureWithSuccess< EitherOfDiverse< @@ -431,6 +469,7 @@ impl pallet_asset_rewards::Config for Runtime { AccountId, TreasurerBodyAccount, >; + type RuntimeFreezeReason = RuntimeFreezeReason; type WeightInfo = weights::pallet_asset_rewards::WeightInfo; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = PalletAssetRewardsBenchmarkHelper; diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index f1d5e8ba0d01..d2209521e992 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -572,6 +572,12 @@ impl pallet_transaction_payment::Config for Runtime { >; } +pub type AssetsFreezerInstance = pallet_assets_freezer::Instance1; +impl pallet_assets_freezer::Config for Runtime { + type RuntimeFreezeReason = RuntimeFreezeReason; + type RuntimeEvent = RuntimeEvent; +} + impl pallet_asset_tx_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Fungibles = Assets; @@ -1738,6 +1744,9 @@ impl pallet_asset_conversion::Config for Runtime { pub type NativeAndAssets = UnionOf, AccountId>; +pub type NativeAndAssetsFreezer = + UnionOf, AccountId>; + parameter_types! { pub const StakingRewardsPalletId: PalletId = PalletId(*b"py/stkrd"); } @@ -1785,12 +1794,14 @@ impl EnsureOrigin for AssetRewardsPermissionedOrigin { impl pallet_asset_rewards::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeFreezeReason = RuntimeFreezeReason; type AssetId = NativeOrWithId; type Balance = u128; type Assets = NativeAndAssets; type PalletId = StakingRewardsPalletId; type CreatePoolOrigin = AssetRewardsPermissionedOrigin; type WeightInfo = (); + type AssetsFreezer = NativeAndAssetsFreezer; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = AssetRewardsBenchmarkHelper; } @@ -2546,6 +2557,9 @@ mod runtime { #[runtime::pallet_index(80)] pub type AssetRewards = pallet_asset_rewards; + + #[runtime::pallet_index(81)] + pub type AssetsFreezer = pallet_assets_freezer::Pallet; } /// The address format for describing accounts. diff --git a/substrate/frame/asset-rewards/Cargo.toml b/substrate/frame/asset-rewards/Cargo.toml index b0ef2c2199eb..dd5d6bf6c20b 100644 --- a/substrate/frame/asset-rewards/Cargo.toml +++ b/substrate/frame/asset-rewards/Cargo.toml @@ -31,6 +31,7 @@ sp-arithmetic = { path = "../../primitives/arithmetic", default-features = false [dev-dependencies] pallet-balances = { path = "../balances" } pallet-assets = { path = "../assets" } +pallet-assets-freezer = { path = "../assets-freezer" } primitive-types = { version = "0.12.0", default-features = false, features = ["codec", "num-traits", "scale-info"] } [features] diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index e37a81fa88f9..cdc6be28861b 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -83,6 +83,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::traits::fungibles::InspectFreeze; use frame_system::pallet_prelude::BlockNumberFor; pub use pallet::*; @@ -165,7 +166,10 @@ pub mod pallet { use super::*; use frame_support::{ pallet_prelude::*, - traits::tokens::{AssetId, Preservation}, + traits::{ + fungibles::MutateFreeze, + tokens::{AssetId, Fortitude, Preservation}, + }, }; use frame_system::pallet_prelude::*; use sp_runtime::{ @@ -176,6 +180,14 @@ pub mod pallet { #[pallet::pallet] pub struct Pallet(_); + /// A reason for the pallet placing a hold on funds. + #[pallet::composite_enum] + pub enum FreezeReason { + /// Funds are staked in the pallet. + #[codec(index = 0)] + Staked, + } + #[pallet::config] pub trait Config: frame_system::Config { /// Overarching event type. @@ -203,6 +215,17 @@ pub mod pallet { type Assets: Inspect + Mutate; + /// Freezer for the Assets. + type AssetsFreezer: MutateFreeze< + Self::AccountId, + Id = Self::RuntimeFreezeReason, + AssetId = Self::AssetId, + Balance = Self::Balance, + >; + + /// The overarching freeze reason. + type RuntimeFreezeReason: From; + /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; @@ -320,6 +343,8 @@ pub mod pallet { ExpiryBlockMustBeInTheFuture, /// An amount overflowed. Overflow, + /// Insufficient funds to create the freeze. + InsufficientFunds, } #[pallet::hooks] @@ -422,7 +447,28 @@ pub mod pallet { Self::update_pool_and_staker_rewards(&pool_info, &staker_info)?; // Try to freeze the staker assets. - // TODO: (blocked https://github.com/paritytech/polkadot-sdk/issues/3342) + let reducible_balance = T::Assets::reducible_balance( + pool_info.staked_asset_id.clone(), + &caller, + Preservation::Expendable, + Fortitude::Force, + ); + + ensure!(reducible_balance >= amount, Error::::InsufficientFunds); + + // Can't use `extend_frozen` because it takes the max of the current and new + // amount instead of summing them. + let prev_frozen = T::AssetsFreezer::balance_frozen( + pool_info.staked_asset_id.clone(), + &FreezeReason::Staked.into(), + &caller, + ); + T::AssetsFreezer::set_freeze( + pool_info.staked_asset_id.clone(), + &FreezeReason::Staked.into(), + &caller, + prev_frozen.checked_add(&amount).ok_or(Error::::Overflow)?, + )?; // Update Pools. pool_info.total_tokens_staked = @@ -461,7 +507,12 @@ pub mod pallet { ensure!(staker_info.amount >= amount, Error::::NotEnoughTokens); // Unfreeze staker assets. - // TODO: (blocked https://github.com/paritytech/polkadot-sdk/issues/3342) + T::AssetsFreezer::decrease_frozen( + pool_info.staked_asset_id.clone(), + &FreezeReason::Staked.into(), + &caller, + amount, + )?; // Update Pools. pool_info.total_tokens_staked.saturating_reduce(amount); diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index ac643bdf685b..1a45391fb152 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -44,6 +44,7 @@ construct_runtime!( System: frame_system, Balances: pallet_balances, Assets: pallet_assets::, + AssetsFreezer: pallet_assets_freezer::, StakingRewards: pallet_staking_rewards, } ); @@ -66,10 +67,10 @@ impl pallet_balances::Config for MockRuntime { type MaxLocks = (); type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; - type FreezeIdentifier = (); - type MaxFreezes = (); + type FreezeIdentifier = RuntimeFreezeReason; + type MaxFreezes = ConstU32<50>; type RuntimeHoldReason = (); - type RuntimeFreezeReason = (); + type RuntimeFreezeReason = RuntimeFreezeReason; } impl pallet_assets::Config for MockRuntime { @@ -87,7 +88,7 @@ impl pallet_assets::Config for MockRuntime { type MetadataDepositPerByte = ConstU128<1>; type ApprovalDeposit = ConstU128<1>; type StringLimit = ConstU32<50>; - type Freezer = (); + type Freezer = AssetsFreezer; type Extra = (); type WeightInfo = (); type CallbackHandle = (); @@ -120,8 +121,18 @@ impl EnsureOrigin for MockPermissionedOrigin { } } +/// Allow Freezes for the `Assets` pallet +pub type AssetsFreezerInstance = pallet_assets_freezer::Instance1; +impl pallet_assets_freezer::Config for MockRuntime { + type RuntimeFreezeReason = RuntimeFreezeReason; + type RuntimeEvent = RuntimeEvent; +} + pub type NativeAndAssets = UnionOf, u128>; +pub type NativeAndAssetsFreezer = + UnionOf, u128>; + #[cfg(feature = "runtime-benchmarks")] pub struct AssetRewardsBenchmarkHelper; #[cfg(feature = "runtime-benchmarks")] @@ -148,9 +159,11 @@ impl Config for MockRuntime { type AssetId = NativeOrWithId; type Balance = ::Balance; type Assets = NativeAndAssets; + type AssetsFreezer = NativeAndAssetsFreezer; type PalletId = StakingRewardsPalletId; type CreatePoolOrigin = MockPermissionedOrigin; type WeightInfo = (); + type RuntimeFreezeReason = RuntimeFreezeReason; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = AssetRewardsBenchmarkHelper; } @@ -161,7 +174,7 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities { pallet_assets::GenesisConfig:: { // Genesis assets: id, owner, is_sufficient, min_balance // pub assets: Vec<(T::AssetId, T::AccountId, bool, T::Balance)>, - assets: vec![(1, 1, true, 10000), (10, 1, true, 10000), (20, 1, true, 10000)], + assets: vec![(1, 1, true, 1), (10, 1, true, 1), (20, 1, true, 1)], // Genesis metadata: id, name, symbol, decimals // pub metadata: Vec<(T::AssetId, Vec, Vec, u8)>, metadata: vec![ diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 7bd661d68322..3758dce2975a 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -16,7 +16,14 @@ // limitations under the License. use crate::{mock::*, *}; -use frame_support::{assert_err, assert_ok, hypothetically, traits::fungible::NativeOrWithId}; +use frame_support::{ + assert_err, assert_ok, hypothetically, + traits::{ + fungible::NativeOrWithId, + fungibles, + tokens::{Fortitude, Preservation}, + }, +}; use sp_runtime::{traits::BadOrigin, ArithmeticError, TokenError}; const DEFAULT_STAKED_ASSET_ID: NativeOrWithId = NativeOrWithId::::WithId(1); @@ -354,6 +361,12 @@ mod stake { let user = 1; create_default_pool(); let pool_id = 0; + let initial_balance = >::reducible_balance( + 1, + &user, + Preservation::Expendable, + Fortitude::Force, + ); // User stakes tokens assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(user), pool_id, 1000)); @@ -370,7 +383,17 @@ mod stake { // Check that the pool's total tokens staked is updated assert_eq!(Pools::::get(pool_id).unwrap().total_tokens_staked, 1000); - // TODO: Check user's frozen balance is updated + // Check user's frozen balance is updated + assert_eq!( + >::reducible_balance( + 1, + &user, + Preservation::Expendable, + Fortitude::Force, + ), + // - extra 1 for ed + initial_balance - 1000 - 1 + ); // User stakes more tokens assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(user), pool_id, 500)); @@ -382,12 +405,21 @@ mod stake { ); // Check that the user's staked amount is updated - assert_eq!(PoolStakers::::get(pool_id, user).unwrap().amount, 1500); + assert_eq!(PoolStakers::::get(pool_id, user).unwrap().amount, 1000 + 500); // Check that the pool's total tokens staked is updated - assert_eq!(Pools::::get(pool_id).unwrap().total_tokens_staked, 1500); + assert_eq!(Pools::::get(pool_id).unwrap().total_tokens_staked, 1000 + 500); - // TODO: Check user's frozen balance is updated + assert_eq!( + >::reducible_balance( + 1, + &user, + Preservation::Expendable, + Fortitude::Force, + ), + // - extra 1 for ed + initial_balance - 1500 - 1 + ); // Event is emitted. assert_eq!(events(), []); @@ -407,7 +439,21 @@ mod stake { #[test] fn fails_for_insufficient_balance() { - // TODO: When freezing assets fails. + new_test_ext().execute_with(|| { + let user = 1; + create_default_pool(); + let pool_id = 0; + let initial_balance = >::reducible_balance( + 1, + &user, + Preservation::Expendable, + Fortitude::Force, + ); + assert_err!( + StakingRewards::stake(RuntimeOrigin::signed(user), pool_id, initial_balance + 1), + Error::::InsufficientFunds + ); + }) } } From d6c61c8bef232daa2bfa358021ab19de1887f5ae Mon Sep 17 00:00:00 2001 From: muharem Date: Mon, 29 Jul 2024 17:21:31 +0200 Subject: [PATCH 105/159] cargo lock, cargo ubmrella --- Cargo.lock | 27 +++++++++++++++++++++++++++ umbrella/Cargo.toml | 9 +++++++++ 2 files changed, 36 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 407ac2b57ce7..76f4eaf2b869 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -793,6 +793,7 @@ dependencies = [ "cumulus-primitives-core", "emulated-integration-tests-common", "frame-support", + "pallet-asset-rewards", "parachains-common", "rococo-emulated-chain", "sp-core", @@ -810,6 +811,7 @@ dependencies = [ "emulated-integration-tests-common", "frame-support", "pallet-asset-conversion", + "pallet-asset-rewards", "pallet-assets", "pallet-balances", "pallet-message-queue", @@ -859,6 +861,7 @@ dependencies = [ "pallet-asset-conversion", "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", + "pallet-asset-rewards", "pallet-assets", "pallet-assets-freezer", "pallet-aura", @@ -938,6 +941,7 @@ dependencies = [ "frame-support", "frame-system", "pallet-asset-conversion", + "pallet-asset-rewards", "pallet-asset-tx-payment", "pallet-assets", "pallet-balances", @@ -989,6 +993,7 @@ dependencies = [ "pallet-asset-conversion", "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", + "pallet-asset-rewards", "pallet-assets", "pallet-assets-freezer", "pallet-aura", @@ -9823,6 +9828,27 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "pallet-asset-rewards" +version = "1.0.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-assets", + "pallet-assets-freezer", + "pallet-balances", + "parity-scale-codec", + "primitive-types", + "scale-info", + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 14.0.0", +] + [[package]] name = "pallet-asset-tx-payment" version = "28.0.0" @@ -14240,6 +14266,7 @@ dependencies = [ "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", + "pallet-asset-rewards", "pallet-asset-tx-payment", "pallet-assets", "pallet-assets-freezer", diff --git a/umbrella/Cargo.toml b/umbrella/Cargo.toml index 8d85e26d8fe7..3ea72cf0cf7f 100644 --- a/umbrella/Cargo.toml +++ b/umbrella/Cargo.toml @@ -67,6 +67,7 @@ std = [ "pallet-asset-conversion-tx-payment?/std", "pallet-asset-conversion?/std", "pallet-asset-rate?/std", + "pallet-asset-rewards?/std", "pallet-asset-tx-payment?/std", "pallet-assets-freezer?/std", "pallet-assets?/std", @@ -263,6 +264,7 @@ runtime-benchmarks = [ "pallet-asset-conversion-ops?/runtime-benchmarks", "pallet-asset-conversion?/runtime-benchmarks", "pallet-asset-rate?/runtime-benchmarks", + "pallet-asset-rewards?/runtime-benchmarks", "pallet-asset-tx-payment?/runtime-benchmarks", "pallet-assets-freezer?/runtime-benchmarks", "pallet-assets?/runtime-benchmarks", @@ -387,6 +389,7 @@ try-runtime = [ "pallet-asset-conversion-tx-payment?/try-runtime", "pallet-asset-conversion?/try-runtime", "pallet-asset-rate?/try-runtime", + "pallet-asset-rewards?/try-runtime", "pallet-asset-tx-payment?/try-runtime", "pallet-assets-freezer?/try-runtime", "pallet-assets?/try-runtime", @@ -600,6 +603,7 @@ runtime = [ "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", + "pallet-asset-rewards", "pallet-asset-tx-payment", "pallet-assets", "pallet-assets-freezer", @@ -1088,6 +1092,11 @@ path = "../substrate/frame/asset-rate" default-features = false optional = true +[dependencies.pallet-asset-rewards] +path = "../substrate/frame/asset-rewards" +default-features = false +optional = true + [dependencies.pallet-asset-tx-payment] path = "../substrate/frame/transaction-payment/asset-tx-payment" default-features = false From 8ec56f4a0217d608a5289a5f17c7a67854955162 Mon Sep 17 00:00:00 2001 From: muharem Date: Mon, 29 Jul 2024 17:44:39 +0200 Subject: [PATCH 106/159] make benchmarks more generic --- .../assets/asset-hub-rococo/src/lib.rs | 30 +- .../assets/asset-hub-westend/src/lib.rs | 30 +- substrate/bin/node/runtime/src/lib.rs | 17 +- .../frame/asset-rewards/src/benchmarking.rs | 461 +++++++----------- substrate/frame/asset-rewards/src/lib.rs | 3 +- substrate/frame/asset-rewards/src/mock.rs | 19 +- substrate/frame/asset-rewards/src/weights.rs | 288 +++++------ 7 files changed, 372 insertions(+), 476 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 7f5c8d4cfbd6..48e8dce24b9e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -864,9 +864,9 @@ impl pallet_asset_conversion_tx_payment::Config for Runtime { type AssetId = xcm::v3::Location; type OnChargeAssetTransaction = SwapAssetAdapter< TokenLocationV3, - NativeAndAssets, + NativeAndNonPoolAssets, AssetConversion, - ResolveAssetTo, + ResolveAssetTo, >; } @@ -1001,18 +1001,26 @@ impl pallet_xcm_bridge_hub_router::Config for Runtim pub struct PalletAssetRewardsBenchmarkHelper; #[cfg(feature = "runtime-benchmarks")] -impl pallet_asset_rewards::benchmarking::BenchmarkHelper +impl pallet_asset_rewards::benchmarking::BenchmarkHelper for PalletAssetRewardsBenchmarkHelper { - fn to_asset_id(seed: u32) -> xcm::v3::Location { - // Any Location is fine for benchmarking. - xcm::v3::Location::ancestor(seed.try_into().unwrap()) - } - fn to_account_id(seed: [u8; 32]) -> AccountId { - seed.into() + fn staked_asset() -> xcm::v3::Location { + xcm::v3::Location::new( + 0, + xcm::v3::Junctions::X2( + xcm::v3::Junction::PalletInstance(::index() as u8), + xcm::v3::Junction::GeneralIndex(100), + ), + ) } - fn sufficient_asset() -> xcm::v3::Location { - xcm::v3::Junction::PalletInstance(::index() as u8).into() + fn reward_asset() -> xcm::v3::Location { + xcm::v3::Location::new( + 0, + xcm::v3::Junctions::X2( + xcm::v3::Junction::PalletInstance(::index() as u8), + xcm::v3::Junction::GeneralIndex(101), + ), + ) } } 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 2bcdb6f6fed1..b6eb5e834dda 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -436,18 +436,26 @@ impl pallet_asset_conversion::Config for Runtime { pub struct PalletAssetRewardsBenchmarkHelper; #[cfg(feature = "runtime-benchmarks")] -impl pallet_asset_rewards::benchmarking::BenchmarkHelper +impl pallet_asset_rewards::benchmarking::BenchmarkHelper for PalletAssetRewardsBenchmarkHelper { - fn to_asset_id(seed: u32) -> xcm::v3::Location { - // Any Location is fine for benchmarking. - xcm::v3::Location::ancestor(seed.try_into().unwrap()) - } - fn to_account_id(seed: [u8; 32]) -> AccountId { - seed.into() + fn staked_asset() -> xcm::v3::Location { + xcm::v3::Location::new( + 0, + xcm::v3::Junctions::X2( + xcm::v3::Junction::PalletInstance(::index() as u8), + xcm::v3::Junction::GeneralIndex(100), + ), + ) } - fn sufficient_asset() -> xcm::v3::Location { - xcm::v3::Junction::PalletInstance(::index() as u8).into() + fn reward_asset() -> xcm::v3::Location { + xcm::v3::Location::new( + 0, + xcm::v3::Junctions::X2( + xcm::v3::Junction::PalletInstance(::index() as u8), + xcm::v3::Junction::GeneralIndex(101), + ), + ) } } @@ -898,9 +906,9 @@ impl pallet_asset_conversion_tx_payment::Config for Runtime { type AssetId = xcm::v3::Location; type OnChargeAssetTransaction = SwapAssetAdapter< WestendLocationV3, - NativeAndAssets, + NativeAndNonPoolAssets, AssetConversion, - ResolveAssetTo, + ResolveAssetTo, >; } diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index af568c2a9638..a6503302a9f1 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1754,21 +1754,14 @@ parameter_types! { pub struct AssetRewardsBenchmarkHelper; #[cfg(feature = "runtime-benchmarks")] -impl pallet_asset_rewards::benchmarking::BenchmarkHelper, AccountId> +impl pallet_asset_rewards::benchmarking::BenchmarkHelper> for AssetRewardsBenchmarkHelper { - fn to_asset_id(seed: u32) -> NativeOrWithId { - if seed == 0 { - NativeOrWithId::::Native - } else { - NativeOrWithId::::WithId(seed) - } - } - fn to_account_id(seed: [u8; 32]) -> AccountId { - seed.into() + fn staked_asset() -> NativeOrWithId { + NativeOrWithId::::WithId(100) } - fn sufficient_asset() -> NativeOrWithId { - NativeOrWithId::::Native + fn reward_asset() -> NativeOrWithId { + NativeOrWithId::::WithId(101) } } diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index c6d2debcda28..c03cae462531 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -16,12 +16,10 @@ // limitations under the License. //! Asset Rewards pallet benchmarking. -//! -//! Note: these benchmarks assume that Root passes the `CreatePoolOrigin` checks. use super::*; use crate::Pallet as AssetRewards; -use frame_benchmarking::v2::*; +use frame_benchmarking::{v2::*, whitelisted_caller, BenchmarkError}; use frame_support::{ assert_ok, traits::{ @@ -29,54 +27,89 @@ use frame_support::{ EnsureOrigin, }, }; -use frame_system::{RawOrigin, RawOrigin::Root}; -use sp_runtime::{traits::One, SaturatedConversion}; +use frame_system::{pallet_prelude::BlockNumberFor, Pallet as System, RawOrigin}; +use sp_runtime::{ + traits::{Bounded, One}, + Saturating, +}; use sp_std::prelude::*; /// Benchmark Helper -pub trait BenchmarkHelper { - /// Convert a u32 to an AssetId - fn to_asset_id(seed: u32) -> AssetId; - /// Convert a [u8; 32] to an AccountId - fn to_account_id(seed: [u8; 32]) -> AccountId; - /// Return the ID of the asset whos minimum balance is sufficient for an account to exist - fn sufficient_asset() -> AssetId; +pub trait BenchmarkHelper { + /// Returns the staked asset id. + /// + /// If the asset does not exist, it will be created by the benchmark. + fn staked_asset() -> AssetId; + /// Returns the reward asset id. + /// + /// If the asset does not exist, it will be created by the benchmark. + fn reward_asset() -> AssetId; +} + +fn pool_lifetime() -> BlockNumberFor { + BlockNumberFor::::max_value() } -/// Create and mint the minimum amount of the sufficient asset. -fn create_and_mint_sufficient(caller: &T::AccountId) +fn create_reward_pool() -> Result where T::Assets: Create + Mutate, { - let sufficient_asset = T::BenchmarkHelper::sufficient_asset(); - create_and_mint_asset::( - &caller, - &sufficient_asset.clone(), - T::Assets::minimum_balance(sufficient_asset), - ); + let caller_origin = + T::CreatePoolOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; + let caller = T::CreatePoolOrigin::ensure_origin(caller_origin.clone()).unwrap(); + + let staked_asset = T::BenchmarkHelper::staked_asset(); + let reward_asset = T::BenchmarkHelper::reward_asset(); + + let min_staked_balance = + T::Assets::minimum_balance(staked_asset.clone()).max(T::Balance::one()); + if !T::Assets::asset_exists(staked_asset.clone()) { + assert_ok!(T::Assets::create( + staked_asset.clone(), + caller.clone(), + true, + min_staked_balance + )); + } + let min_reward_balance = + T::Assets::minimum_balance(reward_asset.clone()).max(T::Balance::one()); + if !T::Assets::asset_exists(reward_asset.clone()) { + assert_ok!(T::Assets::create( + reward_asset.clone(), + caller.clone(), + true, + min_reward_balance + )); + } + + assert_ok!(AssetRewards::::create_pool( + caller_origin.clone(), + Box::new(staked_asset), + Box::new(reward_asset), + // reward rate per block + min_reward_balance, + pool_lifetime::(), + None, + )); + + Ok(caller_origin) } -/// Create the `asset` and mint the `amount` for the `caller`. -fn create_and_mint_asset(caller: &T::AccountId, asset: &T::AssetId, amount: T::Balance) +fn mint_into(caller: &T::AccountId, asset: &T::AssetId) -> T::Balance where - T::Assets: Create + Mutate, + T::Assets: Mutate, { - if !T::Assets::asset_exists(asset.clone()) { - assert_ok!(T::Assets::create(asset.clone(), caller.clone(), true, T::Balance::one())); - } + let min_balance = T::Assets::minimum_balance(asset.clone()); assert_ok!(T::Assets::mint_into( asset.clone(), &caller, - amount + T::Assets::minimum_balance(asset.clone()) + min_balance.saturating_mul(10u32.into()) )); + min_balance } fn assert_last_event(generic_event: ::RuntimeEvent) { - let events = frame_system::Pallet::::events(); - let system_event: ::RuntimeEvent = generic_event.into(); - // compare to the last event record - let frame_system::EventRecord { event, .. } = &events[events.len() - 1]; - assert_eq!(event, &system_event); + System::::assert_last_event(generic_event.into()); } #[benchmarks(where T::Assets: Create + Mutate)] @@ -84,363 +117,215 @@ mod benchmarks { use super::*; #[benchmark] - fn create_pool() { - use super::*; - - let root_acc = T::CreatePoolOrigin::ensure_origin(Root.into()).unwrap(); - let staked_asset = T::BenchmarkHelper::to_asset_id(1); - let reward_asset = T::BenchmarkHelper::to_asset_id(2); - create_and_mint_asset::( - &root_acc, - &staked_asset, - T::Assets::minimum_balance(staked_asset.clone()), - ); - create_and_mint_asset::( - &root_acc, - &reward_asset, - T::Assets::minimum_balance(reward_asset.clone()), - ); + fn create_pool() -> Result<(), BenchmarkError> { + let caller_origin = + T::CreatePoolOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; + let caller = T::CreatePoolOrigin::ensure_origin(caller_origin.clone()).unwrap(); + + let staked_asset = T::BenchmarkHelper::staked_asset(); + let reward_asset = T::BenchmarkHelper::reward_asset(); + + let min_balance = T::Assets::minimum_balance(staked_asset.clone()).max(T::Balance::one()); + if !T::Assets::asset_exists(staked_asset.clone()) { + assert_ok!(T::Assets::create(staked_asset.clone(), caller.clone(), true, min_balance)); + } + let min_balance = T::Assets::minimum_balance(reward_asset.clone()).max(T::Balance::one()); + if !T::Assets::asset_exists(reward_asset.clone()) { + assert_ok!(T::Assets::create(reward_asset.clone(), caller.clone(), true, min_balance)); + } - let block_number_before = frame_system::Pallet::::block_number(); #[extrinsic_call] _( - Root, + caller_origin as T::RuntimeOrigin, Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), - 100u32.into(), - 200u32.into(), + min_balance, + pool_lifetime::(), None, ); assert_last_event::( Event::PoolCreated { - creator: root_acc.clone(), - admin: Some(root_acc), + creator: caller.clone(), + admin: Some(caller), staked_asset_id: staked_asset, reward_asset_id: reward_asset, - reward_rate_per_block: 100u32.into(), - expiry_block: block_number_before + 200u32.into(), - pool_id: 0u32.into(), + reward_rate_per_block: min_balance, + expiry_block: pool_lifetime::(), + pool_id: 0, } .into(), ); + + Ok(()) } #[benchmark] - fn stake() { - use super::*; - - let staker = T::BenchmarkHelper::to_account_id([1u8; 32]); - let staked_asset = T::BenchmarkHelper::to_asset_id(1); - let reward_asset = T::BenchmarkHelper::to_asset_id(0); - create_and_mint_asset::( - &staker, - &staked_asset, - T::Assets::minimum_balance(staked_asset.clone()), - ); - create_and_mint_asset::( - &staker, - &reward_asset, - T::Assets::minimum_balance(reward_asset.clone()), - ); + fn stake() -> Result<(), BenchmarkError> { + create_reward_pool::()?; - assert_ok!(AssetRewards::::create_pool( - Root.into(), - Box::new(staked_asset.clone()), - Box::new(reward_asset.clone()), - 100u32.into(), - 200u32.into(), - None, - )); + let staker: T::AccountId = whitelisted_caller(); + let min_balance = mint_into::(&staker, &T::BenchmarkHelper::staked_asset()); #[extrinsic_call] - _(RawOrigin::Signed(staker.clone()), 0u32.into(), 100u32.into()); + _(RawOrigin::Signed(staker.clone()), 0, min_balance); assert_last_event::( - Event::Staked { caller: staker, pool_id: 0u32.into(), amount: 100u32.into() }.into(), + Event::Staked { caller: staker, pool_id: 0, amount: min_balance }.into(), ); + + Ok(()) } #[benchmark] - fn unstake() { - use super::*; - - let staker = T::BenchmarkHelper::to_account_id([1u8; 32]); - let staked_asset = T::BenchmarkHelper::to_asset_id(1); - let reward_asset = T::BenchmarkHelper::to_asset_id(0); - create_and_mint_asset::( - &staker, - &staked_asset, - T::Assets::minimum_balance(staked_asset.clone()), - ); - create_and_mint_asset::( - &staker, - &reward_asset, - T::Assets::minimum_balance(reward_asset.clone()), - ); + fn unstake() -> Result<(), BenchmarkError> { + create_reward_pool::()?; - assert_ok!(AssetRewards::::create_pool( - Root.into(), - Box::new(staked_asset.clone()), - Box::new(reward_asset.clone()), - 100u32.into(), - 200u32.into(), - None, - )); + let staker: T::AccountId = whitelisted_caller(); + let min_balance = mint_into::(&staker, &T::BenchmarkHelper::staked_asset()); assert_ok!(AssetRewards::::stake( RawOrigin::Signed(staker.clone()).into(), - 0u32.into(), - 100u32.into() + 0, + min_balance, )); #[extrinsic_call] - _(RawOrigin::Signed(staker.clone()), 0u32.into(), 100u32.into()); + _(RawOrigin::Signed(staker.clone()), 0, min_balance); assert_last_event::( - Event::Unstaked { caller: staker, pool_id: 0u32.into(), amount: 100u32.into() }.into(), + Event::Unstaked { caller: staker, pool_id: 0, amount: min_balance }.into(), ); + + Ok(()) } #[benchmark] - fn harvest_rewards() { - use super::*; - - let block_number_before = frame_system::Pallet::::block_number(); - let staker = T::BenchmarkHelper::to_account_id([2u8; 32]); - let staked_asset = T::BenchmarkHelper::to_asset_id(1); - let reward_asset = T::BenchmarkHelper::to_asset_id(2); - create_and_mint_asset::( - &staker, - &staked_asset, - T::Assets::minimum_balance(staked_asset.clone()), - ); - create_and_mint_asset::( - &staker, - &reward_asset, - T::Assets::minimum_balance(reward_asset.clone()), - ); - assert_ok!(AssetRewards::::create_pool( - Root.into(), - Box::new(staked_asset.clone()), - Box::new(reward_asset.clone()), - 100u32.into(), - 200u32.into(), - None, - )); + fn harvest_rewards() -> Result<(), BenchmarkError> { + create_reward_pool::()?; let pool_acc = AssetRewards::::pool_account_id(&0u32).unwrap(); - create_and_mint_sufficient::(&pool_acc); - create_and_mint_asset::(&pool_acc, &reward_asset, 100_000u32.into()); + let min_reward_balance = mint_into::(&pool_acc, &T::BenchmarkHelper::reward_asset()); + + let staker = whitelisted_caller(); + let _ = mint_into::(&staker, &T::BenchmarkHelper::staked_asset()); assert_ok!(AssetRewards::::stake( RawOrigin::Signed(staker.clone()).into(), - 0u32.into(), - 100u32.into() + 0, + T::Balance::one(), )); - #[extrinsic_call] - _(RawOrigin::Signed(staker.clone()), 0u32.into(), None); - - let block_number_after = frame_system::Pallet::::block_number(); + System::::set_block_number( + frame_system::Pallet::::block_number() + BlockNumberFor::::one(), + ); - // In tests a block doesn't pass but when running benchmarks for node-template one does. - // Not sure why, but adding this to correctly calculate the harvested amount. - // - // TODO: Before merging understand this - let blocks_elapsed = block_number_after - block_number_before; + #[extrinsic_call] + _(RawOrigin::Signed(staker.clone()), 0, None); assert_last_event::( Event::RewardsHarvested { caller: staker.clone(), staker, - pool_id: 0u32.into(), - amount: (blocks_elapsed * 100u8.into()).saturated_into::().into(), + pool_id: 0, + amount: min_reward_balance, } .into(), ); + + Ok(()) } #[benchmark] - fn set_pool_reward_rate_per_block() { - use super::*; - - let acc = T::BenchmarkHelper::to_account_id([3u8; 32]); - let staked_asset = T::BenchmarkHelper::to_asset_id(1); - let reward_asset = T::BenchmarkHelper::to_asset_id(5); - create_and_mint_asset::( - &acc, - &staked_asset, - T::Assets::minimum_balance(staked_asset.clone()), - ); - create_and_mint_asset::( - &acc, - &reward_asset, - T::Assets::minimum_balance(reward_asset.clone()), - ); - - assert_ok!(AssetRewards::::create_pool( - Root.into(), - Box::new(staked_asset.clone()), - Box::new(reward_asset.clone()), - 100u32.into(), - 200u32.into(), - None, - )); + fn set_pool_reward_rate_per_block() -> Result<(), BenchmarkError> { + let caller_origin = create_reward_pool::()?; + let new_reward_rate_per_block = T::Balance::from(5u32); #[extrinsic_call] - _(Root, 0u32.into(), 5u32.into()); + _(caller_origin as T::RuntimeOrigin, 0, new_reward_rate_per_block); assert_last_event::( - Event::PoolRewardRateModified { - pool_id: 0u32.into(), - new_reward_rate_per_block: 5u32.into(), - } - .into(), + Event::PoolRewardRateModified { pool_id: 0, new_reward_rate_per_block }.into(), ); + Ok(()) } #[benchmark] - fn set_pool_admin() { - use super::*; - - let new_admin = T::BenchmarkHelper::to_account_id([2u8; 32]); - let staked_asset = T::BenchmarkHelper::to_asset_id(1); - let reward_asset = T::BenchmarkHelper::to_asset_id(0); - create_and_mint_asset::( - &new_admin, - &staked_asset, - T::Assets::minimum_balance(staked_asset.clone()), - ); - create_and_mint_asset::( - &new_admin, - &reward_asset, - T::Assets::minimum_balance(reward_asset.clone()), - ); - - assert_ok!(AssetRewards::::create_pool( - Root.into(), - Box::new(staked_asset.clone()), - Box::new(reward_asset.clone()), - 100u32.into(), - 200u32.into(), - None, - )); + fn set_pool_admin() -> Result<(), BenchmarkError> { + let caller_origin = create_reward_pool::()?; + let new_admin: T::AccountId = whitelisted_caller(); #[extrinsic_call] - _(Root, 0u32.into(), new_admin.clone()); + _(caller_origin as T::RuntimeOrigin, 0, new_admin.clone()); assert_last_event::( - Event::PoolAdminModified { pool_id: 0u32.into(), new_admin: Some(new_admin) }.into(), + Event::PoolAdminModified { pool_id: 0, new_admin: Some(new_admin) }.into(), ); + + Ok(()) } #[benchmark] - fn set_pool_expiry_block() { - use super::*; - - let staked_asset = T::BenchmarkHelper::to_asset_id(2); - let reward_asset = T::BenchmarkHelper::to_asset_id(5); - let acc = T::BenchmarkHelper::to_account_id([5u8; 32]); - create_and_mint_asset::( - &acc, - &staked_asset, - T::Assets::minimum_balance(staked_asset.clone()), - ); - create_and_mint_asset::( - &acc, - &reward_asset, - T::Assets::minimum_balance(reward_asset.clone()), - ); + fn set_pool_expiry_block() -> Result<(), BenchmarkError> { + let create_origin = create_reward_pool::()?; - assert_ok!(AssetRewards::::create_pool( - Root.into(), - Box::new(staked_asset.clone()), - Box::new(reward_asset.clone()), - 100u32.into(), - 200u32.into(), - None, - )); + let new_expiry_block = pool_lifetime::() - BlockNumberFor::::one(); #[extrinsic_call] - _(Root, 0u32.into(), 1000u32.into()); + _(create_origin as T::RuntimeOrigin, 0, new_expiry_block); assert_last_event::( - Event::PoolExpiryBlockModified { - pool_id: 0u32.into(), - new_expiry_block: 1000u32.into(), - } - .into(), + Event::PoolExpiryBlockModified { pool_id: 0, new_expiry_block }.into(), ); + + Ok(()) } #[benchmark] - fn deposit_reward_tokens() { - use super::*; - - let acc = T::BenchmarkHelper::to_account_id([3u8; 32]); - let staked_asset = T::BenchmarkHelper::to_asset_id(1); - let reward_asset = T::BenchmarkHelper::to_asset_id(4); - create_and_mint_asset::(&acc, &reward_asset, 100_000u32.into()); - create_and_mint_asset::(&acc, &staked_asset, 100_000u32.into()); - - assert_ok!(AssetRewards::::create_pool( - Root.into(), - Box::new(staked_asset.clone()), - Box::new(reward_asset.clone()), - 100u32.into(), - 200u32.into(), - None, - )); + fn deposit_reward_tokens() -> Result<(), BenchmarkError> { + create_reward_pool::()?; + let caller = whitelisted_caller(); + let reward_asset = T::BenchmarkHelper::reward_asset(); let pool_acc = AssetRewards::::pool_account_id(&0u32).unwrap(); - create_and_mint_sufficient::(&pool_acc); + let min_balance = mint_into::(&caller, &reward_asset); - let balance_before = T::Assets::balance(reward_asset.clone(), &acc); + let balance_before = T::Assets::balance(reward_asset.clone(), &pool_acc); #[extrinsic_call] - _(RawOrigin::Signed(acc.clone()), 0u32.into(), 10_000u32.into()); + _(RawOrigin::Signed(caller), 0, min_balance); - let balance_after = T::Assets::balance(reward_asset.clone(), &acc); + let balance_after = T::Assets::balance(reward_asset, &pool_acc); - assert_eq!(balance_after, balance_before - 10_000u32.into()); + assert_eq!(balance_after, balance_before + min_balance); + + Ok(()) } #[benchmark] - fn withdraw_reward_tokens() { - use super::*; - - let acc = T::BenchmarkHelper::to_account_id([3u8; 32]); - let staked_asset = T::BenchmarkHelper::to_asset_id(1); - let reward_asset = T::BenchmarkHelper::to_asset_id(2); - create_and_mint_asset::(&acc, &staked_asset, 10000u32.into()); - create_and_mint_asset::(&acc, &reward_asset, 10000u32.into()); - - assert_ok!(AssetRewards::::create_pool( - Root.into(), - Box::new(staked_asset.clone()), - Box::new(reward_asset.clone()), - 100u32.into(), - 200u32.into(), - None, - )); - let pool_acc = AssetRewards::::pool_account_id(&0u32).unwrap(); - create_and_mint_sufficient::(&pool_acc); + fn withdraw_reward_tokens() -> Result<(), BenchmarkError> { + let create_origin = create_reward_pool::()?; + let caller = whitelisted_caller(); - let balance_before = T::Assets::balance(reward_asset.clone(), &acc); + let reward_asset = T::BenchmarkHelper::reward_asset(); + let min_balance = mint_into::(&caller, &reward_asset); assert_ok!(AssetRewards::::deposit_reward_tokens( - RawOrigin::Signed(acc.clone()).into(), - 0u32.into(), - 100u32.into() + RawOrigin::Signed(caller.clone()).into(), + 0, + min_balance, )); + let pool_acc = AssetRewards::::pool_account_id(&0).unwrap(); + let balance_before = T::Assets::balance(reward_asset.clone(), &pool_acc); + #[extrinsic_call] - _(Root, 0u32.into(), 50u32.into(), acc.clone()); + _(create_origin as T::RuntimeOrigin, 0, min_balance, caller); + + let balance_after = T::Assets::balance(reward_asset.clone(), &pool_acc); - let balance_after = T::Assets::balance(reward_asset.clone(), &acc); + assert_eq!(balance_before, balance_after + min_balance); - // Deposited 100, withdrew 50 - assert_eq!(balance_after, balance_before - 50u32.into()); + Ok(()) } impl_benchmark_test_suite!(AssetRewards, crate::mock::new_test_ext(), crate::mock::MockRuntime); diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index cdc6be28861b..4c6baccf7b7b 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -231,7 +231,7 @@ pub mod pallet { /// Helper for benchmarking. #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper: benchmarking::BenchmarkHelper; + type BenchmarkHelper: benchmarking::BenchmarkHelper; } /// State of pool stakers. @@ -417,6 +417,7 @@ pub mod pallet { // Insert it into storage. let pool_id = NextPoolId::::get(); Pools::::insert(pool_id, pool); + // TODO should be checked add NextPoolId::::put(pool_id.saturating_add(1)); // Emit created event. diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index d330277f4c30..ce12cd60860f 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -136,21 +136,12 @@ pub type NativeAndAssetsFreezer = #[cfg(feature = "runtime-benchmarks")] pub struct AssetRewardsBenchmarkHelper; #[cfg(feature = "runtime-benchmarks")] -impl BenchmarkHelper, u128> for AssetRewardsBenchmarkHelper { - fn to_asset_id(seed: u32) -> NativeOrWithId { - if seed == 0 { - NativeOrWithId::::Native - } else { - NativeOrWithId::::WithId(seed) - } - } - fn to_account_id(seed: [u8; 32]) -> u128 { - // only 16 bytes fit into u128 - let bytes = <[u8; 16]>::try_from(&seed[0..16]).unwrap(); - u128::from_be_bytes(bytes) +impl BenchmarkHelper> for AssetRewardsBenchmarkHelper { + fn staked_asset() -> NativeOrWithId { + NativeOrWithId::::WithId(101) } - fn sufficient_asset() -> NativeOrWithId { - NativeOrWithId::::Native + fn reward_asset() -> NativeOrWithId { + NativeOrWithId::::WithId(102) } } diff --git a/substrate/frame/asset-rewards/src/weights.rs b/substrate/frame/asset-rewards/src/weights.rs index 7deb3f6b77a1..09dd85e1b3ff 100644 --- a/substrate/frame/asset-rewards/src/weights.rs +++ b/substrate/frame/asset-rewards/src/weights.rs @@ -18,25 +18,23 @@ //! Autogenerated weights for `pallet_asset_rewards` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-04-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-07-29, STEPS: `50`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `cob`, CPU: `` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// ./target/debug/substrate-node // benchmark // pallet +// --chain=dev // --steps=50 -// --repeat=20 +// --repeat=2 +// --pallet=pallet-asset-rewards // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_asset_rewards -// --chain=dev -// --header=./substrate/HEADER-APACHE2 -// --output=./substrate/frame/asset-rewards/src/weights.rs +// --output=./substrate/frame/asset-rewards/src/._weights0.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -63,238 +61,250 @@ pub trait WeightInfo { /// Weights for `pallet_asset_rewards` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::NextPoolId` (r:1 w:1) - /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::Pools` (r:0 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn create_pool() -> Weight { // Proof Size summary in bytes: - // Measured: `333` - // Estimated: `3675` - // Minimum execution time: 15_461_000 picoseconds. - Weight::from_parts(16_048_000, 3675) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `109` + // Estimated: `1489` + // Minimum execution time: 116_000_000 picoseconds. + Weight::from_parts(135_000_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) - /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:0) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) fn stake() -> Weight { // Proof Size summary in bytes: - // Measured: `277` - // Estimated: `3742` - // Minimum execution time: 17_959_000 picoseconds. - Weight::from_parts(18_708_000, 3742) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `336` + // Estimated: `4764` + // Minimum execution time: 463_000_000 picoseconds. + Weight::from_parts(488_000_000, 4764) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) - /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:0) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) fn unstake() -> Weight { // Proof Size summary in bytes: - // Measured: `417` - // Estimated: `3882` - // Minimum execution time: 21_580_000 picoseconds. - Weight::from_parts(22_478_000, 3882) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `532` + // Estimated: `4764` + // Minimum execution time: 455_000_000 picoseconds. + Weight::from_parts(458_000_000, 4764) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) - /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn harvest_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `660` - // Estimated: `6196` - // Minimum execution time: 58_827_000 picoseconds. - Weight::from_parts(59_910_000, 6196) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + // Measured: `517` + // Estimated: `3593` + // Minimum execution time: 633_000_000 picoseconds. + Weight::from_parts(641_000_000, 3593) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn set_pool_reward_rate_per_block() -> Weight { // Proof Size summary in bytes: - // Measured: `277` - // Estimated: `3742` - // Minimum execution time: 13_068_000 picoseconds. - Weight::from_parts(13_753_000, 3742) + // Measured: `274` + // Estimated: `3584` + // Minimum execution time: 119_000_000 picoseconds. + Weight::from_parts(123_000_000, 3584) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn set_pool_admin() -> Weight { // Proof Size summary in bytes: - // Measured: `277` - // Estimated: `3742` - // Minimum execution time: 12_921_000 picoseconds. - Weight::from_parts(13_542_000, 3742) + // Measured: `274` + // Estimated: `3584` + // Minimum execution time: 125_000_000 picoseconds. + Weight::from_parts(141_000_000, 3584) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn set_pool_expiry_block() -> Weight { // Proof Size summary in bytes: - // Measured: `277` - // Estimated: `3742` - // Minimum execution time: 13_628_000 picoseconds. - Weight::from_parts(14_245_000, 3742) + // Measured: `274` + // Estimated: `3584` + // Minimum execution time: 127_000_000 picoseconds. + Weight::from_parts(166_000_000, 3584) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn deposit_reward_tokens() -> Weight { // Proof Size summary in bytes: - // Measured: `520` - // Estimated: `6196` - // Minimum execution time: 45_885_000 picoseconds. - Weight::from_parts(47_405_000, 6196) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `274` + // Estimated: `3593` + // Minimum execution time: 519_000_000 picoseconds. + Weight::from_parts(527_000_000, 3593) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn withdraw_reward_tokens() -> Weight { // Proof Size summary in bytes: - // Measured: `520` - // Estimated: `6196` - // Minimum execution time: 45_973_000 picoseconds. - Weight::from_parts(47_179_000, 6196) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `377` + // Estimated: `3593` + // Minimum execution time: 598_000_000 picoseconds. + Weight::from_parts(627_000_000, 3593) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } } // For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::NextPoolId` (r:1 w:1) - /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::Pools` (r:0 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn create_pool() -> Weight { // Proof Size summary in bytes: - // Measured: `333` - // Estimated: `3675` - // Minimum execution time: 15_461_000 picoseconds. - Weight::from_parts(16_048_000, 3675) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Measured: `109` + // Estimated: `1489` + // Minimum execution time: 116_000_000 picoseconds. + Weight::from_parts(135_000_000, 1489) + .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) - /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:0) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) fn stake() -> Weight { // Proof Size summary in bytes: - // Measured: `277` - // Estimated: `3742` - // Minimum execution time: 17_959_000 picoseconds. - Weight::from_parts(18_708_000, 3742) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `336` + // Estimated: `4764` + // Minimum execution time: 463_000_000 picoseconds. + Weight::from_parts(488_000_000, 4764) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) - /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:1) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:0) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) fn unstake() -> Weight { // Proof Size summary in bytes: - // Measured: `417` - // Estimated: `3882` - // Minimum execution time: 21_580_000 picoseconds. - Weight::from_parts(22_478_000, 3882) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `532` + // Estimated: `4764` + // Minimum execution time: 455_000_000 picoseconds. + Weight::from_parts(458_000_000, 4764) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) - /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn harvest_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `660` - // Estimated: `6196` - // Minimum execution time: 58_827_000 picoseconds. - Weight::from_parts(59_910_000, 6196) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + // Measured: `517` + // Estimated: `3593` + // Minimum execution time: 633_000_000 picoseconds. + Weight::from_parts(641_000_000, 3593) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn set_pool_reward_rate_per_block() -> Weight { // Proof Size summary in bytes: - // Measured: `277` - // Estimated: `3742` - // Minimum execution time: 13_068_000 picoseconds. - Weight::from_parts(13_753_000, 3742) + // Measured: `274` + // Estimated: `3584` + // Minimum execution time: 119_000_000 picoseconds. + Weight::from_parts(123_000_000, 3584) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn set_pool_admin() -> Weight { // Proof Size summary in bytes: - // Measured: `277` - // Estimated: `3742` - // Minimum execution time: 12_921_000 picoseconds. - Weight::from_parts(13_542_000, 3742) + // Measured: `274` + // Estimated: `3584` + // Minimum execution time: 125_000_000 picoseconds. + Weight::from_parts(141_000_000, 3584) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn set_pool_expiry_block() -> Weight { // Proof Size summary in bytes: - // Measured: `277` - // Estimated: `3742` - // Minimum execution time: 13_628_000 picoseconds. - Weight::from_parts(14_245_000, 3742) + // Measured: `274` + // Estimated: `3584` + // Minimum execution time: 127_000_000 picoseconds. + Weight::from_parts(166_000_000, 3584) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn deposit_reward_tokens() -> Weight { // Proof Size summary in bytes: - // Measured: `520` - // Estimated: `6196` - // Minimum execution time: 45_885_000 picoseconds. - Weight::from_parts(47_405_000, 6196) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `274` + // Estimated: `3593` + // Minimum execution time: 519_000_000 picoseconds. + Weight::from_parts(527_000_000, 3593) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:2) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn withdraw_reward_tokens() -> Weight { // Proof Size summary in bytes: - // Measured: `520` - // Estimated: `6196` - // Minimum execution time: 45_973_000 picoseconds. - Weight::from_parts(47_179_000, 6196) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `377` + // Estimated: `3593` + // Minimum execution time: 598_000_000 picoseconds. + Weight::from_parts(627_000_000, 3593) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } } From 872e4bd9961f4d201924bc292f644a9e16f2b459 Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 31 Jul 2024 11:54:01 +0200 Subject: [PATCH 107/159] fix broken imports --- .../emulated/tests/assets/asset-hub-rococo/src/lib.rs | 3 ++- .../src/tests/treasury_asset_reward_pool.rs | 8 +++----- .../emulated/tests/assets/asset-hub-westend/src/lib.rs | 9 ++++++--- .../src/tests/treasury_asset_reward_pool.rs | 8 +++----- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs index 6309c0584107..040f3afbb7a1 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs @@ -51,7 +51,7 @@ mod imports { asset_hub_rococo_runtime::{ xcm_config::{ self as ahr_xcm_config, TokenLocation as RelayLocation, - XcmConfig as AssetHubRococoXcmConfig, + TokenLocationV3 as RelayLocationV3, XcmConfig as AssetHubRococoXcmConfig, }, AssetConversionOrigin as AssetHubRococoAssetConversionOrigin, ExistentialDeposit as AssetHubRococoExistentialDeposit, @@ -72,6 +72,7 @@ mod imports { genesis::ED as ROCOCO_ED, rococo_runtime::{ governance as rococo_governance, + governance::pallet_custom_origins::Origin::Treasurer, xcm_config::{ UniversalLocation as RococoUniversalLocation, XcmConfig as RococoXcmConfig, }, diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs index 2fa9c76ecfdf..677399ed4aab 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs @@ -14,7 +14,6 @@ // limitations under the License. use crate::imports::*; -use asset_hub_rococo_runtime::xcm_config::TokenLocationV3; use codec::Encode; use emulated_integration_tests_common::ASSET_HUB_ROCOCO_ID; use frame_support::{assert_ok, sp_runtime::traits::Dispatchable}; @@ -29,8 +28,8 @@ fn treasury_creates_asset_reward_pool() { type RococoRuntimeEvent = ::RuntimeEvent; type RococoRuntimeOrigin = ::RuntimeOrigin; - let staked_asset_id = bx!(TokenLocationV3::get()); - let reward_asset_id = bx!(TokenLocationV3::get()); + let staked_asset_id = bx!(RelayLocationV3::get()); + let reward_asset_id = bx!(RelayLocationV3::get()); let reward_rate_per_block = 1_000_000_000; let lifetime = 1_000_000_000; @@ -61,8 +60,7 @@ fn treasury_creates_asset_reward_pool() { ]))), }); - let treasury_origin: RococoRuntimeOrigin = - rococo_runtime::governance::pallet_custom_origins::Origin::Treasurer.into(); + let treasury_origin: RococoRuntimeOrigin = Treasurer.into(); assert_ok!(create_pool_call.dispatch(treasury_origin)); assert_expected_events!( diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs index 060c3fb39254..f04fb30cee3e 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs @@ -51,7 +51,7 @@ mod imports { asset_hub_westend_runtime::{ xcm_config::{ self as ahw_xcm_config, WestendLocation as RelayLocation, - XcmConfig as AssetHubWestendXcmConfig, + WestendLocationV3 as RelayLocationV3, XcmConfig as AssetHubWestendXcmConfig, }, AssetConversionOrigin as AssetHubWestendAssetConversionOrigin, ExistentialDeposit as AssetHubWestendExistentialDeposit, @@ -71,8 +71,11 @@ mod imports { }, westend_emulated_chain::{ genesis::ED as WESTEND_ED, - westend_runtime::xcm_config::{ - UniversalLocation as WestendUniversalLocation, XcmConfig as WestendXcmConfig, + westend_runtime::{ + governance::pallet_custom_origins::Origin::Treasurer, + xcm_config::{ + UniversalLocation as WestendUniversalLocation, XcmConfig as WestendXcmConfig, + }, }, WestendRelayPallet as WestendPallet, }, diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs index 2d14ebc2500e..0d7da6faf322 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs @@ -14,7 +14,6 @@ // limitations under the License. use crate::imports::*; -use asset_hub_westend_runtime::xcm_config::WestendLocationV3; use codec::Encode; use emulated_integration_tests_common::ASSET_HUB_WESTEND_ID; use frame_support::{assert_ok, sp_runtime::traits::Dispatchable}; @@ -29,8 +28,8 @@ fn treasury_creates_asset_reward_pool() { type WestendRuntimeEvent = ::RuntimeEvent; type WestendRuntimeOrigin = ::RuntimeOrigin; - let staked_asset_id = bx!(WestendLocationV3::get()); - let reward_asset_id = bx!(WestendLocationV3::get()); + let staked_asset_id = bx!(RelayLocationV3::get()); + let reward_asset_id = bx!(RelayLocationV3::get()); let reward_rate_per_block = 1_000_000_000; let lifetime = 1_000_000_000; @@ -61,8 +60,7 @@ fn treasury_creates_asset_reward_pool() { ]))), }); - let treasury_origin: WestendRuntimeOrigin = - westend_runtime::governance::pallet_custom_origins::Origin::Treasurer.into(); + let treasury_origin: WestendRuntimeOrigin = Treasurer.into(); assert_ok!(create_pool_call.dispatch(treasury_origin)); assert_expected_events!( From 5459c97a1af0eb3e79102136c3dd8dc7a3b27f5f Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 31 Jul 2024 14:42:06 +0200 Subject: [PATCH 108/159] ensure_successful for Consideration types --- substrate/frame/support/src/traits/storage.rs | 6 +++ .../support/src/traits/tokens/fungible/mod.rs | 38 +++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/substrate/frame/support/src/traits/storage.rs b/substrate/frame/support/src/traits/storage.rs index a954af14d259..ac6cbfd5d302 100644 --- a/substrate/frame/support/src/traits/storage.rs +++ b/substrate/frame/support/src/traits/storage.rs @@ -239,6 +239,10 @@ pub trait Consideration: fn burn(self, _: &AccountId) { let _ = self; } + /// Ensure that creating a ticket for a given account and footprint will be successful if done + /// immediately after this call. + #[cfg(feature = "runtime-benchmarks")] + fn ensure_successful(who: &AccountId, new: Footprint); } impl Consideration for () { @@ -251,6 +255,8 @@ impl Consideration for () { fn drop(self, _: &A) -> Result<(), DispatchError> { Ok(()) } + #[cfg(feature = "runtime-benchmarks")] + fn ensure_successful(_: &A, _: F) {} } macro_rules! impl_incrementable { diff --git a/substrate/frame/support/src/traits/tokens/fungible/mod.rs b/substrate/frame/support/src/traits/tokens/fungible/mod.rs index f40e494b930d..ae9a9dd90854 100644 --- a/substrate/frame/support/src/traits/tokens/fungible/mod.rs +++ b/substrate/frame/support/src/traits/tokens/fungible/mod.rs @@ -164,6 +164,8 @@ use codec::{Decode, Encode, MaxEncodedLen}; use core::marker::PhantomData; use frame_support_procedural::{CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound}; use scale_info::TypeInfo; +#[cfg(feature = "runtime-benchmarks")] +use sp_runtime::Saturating; use super::{ Fortitude::{Force, Polite}, @@ -209,8 +211,9 @@ pub struct FreezeConsideration(F::Balance, PhantomData ( where F: MutateFreeze; impl< - A: 'static, - F: 'static + MutateFreeze, + A: 'static + Eq, + #[cfg(not(feature = "runtime-benchmarks"))] F: 'static + MutateFreeze, + #[cfg(feature = "runtime-benchmarks")] F: 'static + MutateFreeze + Mutate, R: 'static + Get, D: 'static + Convert, Fp: 'static, @@ -241,6 +244,10 @@ impl< fn drop(self, who: &A) -> Result<(), DispatchError> { F::decrease_frozen(&R::get(), who, self.0).map(|_| ()) } + #[cfg(feature = "runtime-benchmarks")] + fn ensure_successful(who: &A, fp: Fp) { + let _ = F::mint_into(who, F::minimum_balance().saturating_add(D::convert(fp))); + } } /// Consideration method using a `fungible` balance frozen as the cost exacted for the footprint. @@ -263,8 +270,9 @@ pub struct HoldConsideration( where F: MutateHold; impl< - A: 'static, - F: 'static + MutateHold, + A: 'static + Eq, + #[cfg(not(feature = "runtime-benchmarks"))] F: 'static + MutateHold, + #[cfg(feature = "runtime-benchmarks")] F: 'static + MutateHold + Mutate, R: 'static + Get, D: 'static + Convert, Fp: 'static, @@ -298,6 +306,10 @@ impl< fn burn(self, who: &A) { let _ = F::burn_held(&R::get(), who, self.0, BestEffort, Force); } + #[cfg(feature = "runtime-benchmarks")] + fn ensure_successful(who: &A, fp: Fp) { + let _ = F::mint_into(who, F::minimum_balance().saturating_add(D::convert(fp))); + } } /// Basic consideration method using a `fungible` balance frozen as the cost exacted for the @@ -321,8 +333,9 @@ impl< #[codec(mel_bound())] pub struct LoneFreezeConsideration(PhantomData (A, Fx, Rx, D, Fp)>); impl< - A: 'static, - Fx: 'static + MutateFreeze, + A: 'static + Eq, + #[cfg(not(feature = "runtime-benchmarks"))] Fx: 'static + MutateFreeze, + #[cfg(feature = "runtime-benchmarks")] Fx: 'static + MutateFreeze + Mutate, Rx: 'static + Get, D: 'static + Convert, Fp: 'static, @@ -349,6 +362,10 @@ impl< fn drop(self, who: &A) -> Result<(), DispatchError> { Fx::thaw(&Rx::get(), who).map(|_| ()) } + #[cfg(feature = "runtime-benchmarks")] + fn ensure_successful(who: &A, fp: Fp) { + let _ = Fx::mint_into(who, Fx::minimum_balance().saturating_add(D::convert(fp))); + } } /// Basic consideration method using a `fungible` balance placed on hold as the cost exacted for the @@ -372,8 +389,9 @@ impl< #[codec(mel_bound())] pub struct LoneHoldConsideration(PhantomData (A, Fx, Rx, D, Fp)>); impl< - A: 'static, - F: 'static + MutateHold, + A: 'static + Eq, + #[cfg(not(feature = "runtime-benchmarks"))] F: 'static + MutateHold, + #[cfg(feature = "runtime-benchmarks")] F: 'static + MutateHold + Mutate, R: 'static + Get, D: 'static + Convert, Fp: 'static, @@ -403,4 +421,8 @@ impl< fn burn(self, who: &A) { let _ = F::burn_all_held(&R::get(), who, BestEffort, Force); } + #[cfg(feature = "runtime-benchmarks")] + fn ensure_successful(who: &A, fp: Fp) { + let _ = F::mint_into(who, F::minimum_balance().saturating_add(D::convert(fp))); + } } From eb956c1ce0b299f315882f9e34e0bfe474b0dd3e Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 31 Jul 2024 14:43:30 +0200 Subject: [PATCH 109/159] add Consideration for pool creation --- .../assets/asset-hub-rococo/src/lib.rs | 26 +- .../assets/asset-hub-westend/src/lib.rs | 24 +- .../asset-hub-westend/src/xcm_config.rs | 4 +- substrate/bin/node/runtime/src/lib.rs | 37 +-- .../frame/asset-rewards/src/benchmarking.rs | 8 +- substrate/frame/asset-rewards/src/lib.rs | 36 ++- substrate/frame/asset-rewards/src/mock.rs | 22 +- substrate/frame/asset-rewards/src/weights.rs | 270 +++++++++++------- 8 files changed, 261 insertions(+), 166 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 48e8dce24b9e..10c13ee8d1bb 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -61,9 +61,11 @@ use frame_support::{ genesis_builder_helper::{build_state, get_preset}, ord_parameter_types, parameter_types, traits::{ - fungible, fungibles, tokens::imbalance::ResolveAssetTo, AsEnsureOriginWithArg, ConstBool, - ConstU128, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Equals, InstanceFilter, - TransformOrigin, + fungible::{self, HoldConsideration}, + fungibles, + tokens::imbalance::ResolveAssetTo, + AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, EitherOfDiverse, + Equals, InstanceFilter, LinearStoragePrice, TransformOrigin, }, weights::{ConstantMultiplier, Weight, WeightToFee as _}, BoundedVec, PalletId, @@ -1026,8 +1028,9 @@ impl pallet_asset_rewards::benchmarking::BenchmarkHelper parameter_types! { pub const AssetRewardsPalletId: PalletId = PalletId(*b"py/astrd"); - pub const TreasurerBodyId: BodyId = BodyId::Treasury; - pub TreasurerBodyAccount: AccountId = LocationToAccountId::convert_location(&RelayTreasuryLocation::get()).unwrap(); + pub const PoolCreationDeposit: Balance = deposit(1, 95); + pub const RewardsPoolCreationHoldReason: RuntimeHoldReason = + RuntimeHoldReason::AssetRewards(pallet_asset_rewards::HoldReason::PoolCreation); } impl pallet_asset_rewards::Config for Runtime { @@ -1037,15 +1040,14 @@ impl pallet_asset_rewards::Config for Runtime { type Assets = NativeAndAllAssets; type AssetsFreezer = NativeAndAllAssetsFreezer; type AssetId = xcm::v3::Location; - type CreatePoolOrigin = EnsureWithSuccess< - EitherOfDiverse< - EnsureRoot, - EnsureXcm>, - >, + type CreatePoolOrigin = EnsureSigned; + type RuntimeFreezeReason = RuntimeFreezeReason; + type Consideration = HoldConsideration< AccountId, - TreasurerBodyAccount, + Balances, + RewardsPoolCreationHoldReason, + LinearStoragePrice, Balance>, >; - type RuntimeFreezeReason = RuntimeFreezeReason; type WeightInfo = weights::pallet_asset_rewards::WeightInfo; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = PalletAssetRewardsBenchmarkHelper; 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 b6eb5e834dda..c9566818dd98 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -43,10 +43,12 @@ use frame_support::{ genesis_builder_helper::{build_state, get_preset}, ord_parameter_types, parameter_types, traits::{ - fungible, fungibles, + fungible, + fungible::HoldConsideration, + fungibles, tokens::{imbalance::ResolveAssetTo, nonfungibles_v2::Inspect}, AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, EitherOfDiverse, - Equals, InstanceFilter, TransformOrigin, + Equals, InstanceFilter, LinearStoragePrice, TransformOrigin, }, weights::{ConstantMultiplier, Weight, WeightToFee as _}, BoundedVec, PalletId, @@ -461,8 +463,9 @@ impl pallet_asset_rewards::benchmarking::BenchmarkHelper parameter_types! { pub const AssetRewardsPalletId: PalletId = PalletId(*b"py/astrd"); - pub const TreasurerBodyId: BodyId = BodyId::Treasury; - pub TreasurerBodyAccount: AccountId = LocationToAccountId::convert_location(&RelayTreasuryLocation::get()).unwrap(); + pub const PoolCreationDeposit: Balance = deposit(1, 95); + pub const RewardsPoolCreationHoldReason: RuntimeHoldReason = + RuntimeHoldReason::AssetRewards(pallet_asset_rewards::HoldReason::PoolCreation); } impl pallet_asset_rewards::Config for Runtime { @@ -472,15 +475,14 @@ impl pallet_asset_rewards::Config for Runtime { type Assets = NativeAndAllAssets; type AssetsFreezer = NativeAndAllAssetsFreezer; type AssetId = xcm::v3::Location; - type CreatePoolOrigin = EnsureWithSuccess< - EitherOfDiverse< - EnsureRoot, - EnsureXcm>, - >, + type CreatePoolOrigin = EnsureSigned; + type RuntimeFreezeReason = RuntimeFreezeReason; + type Consideration = HoldConsideration< AccountId, - TreasurerBodyAccount, + Balances, + RewardsPoolCreationHoldReason, + LinearStoragePrice, Balance>, >; - type RuntimeFreezeReason = RuntimeFreezeReason; type WeightInfo = weights::pallet_asset_rewards::WeightInfo; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = PalletAssetRewardsBenchmarkHelper; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index 7ba78f0752df..8c502bd90aff 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -47,7 +47,7 @@ use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, - DenyReserveTransferToRelayChain, DenyThenTry, DescribeFamily, DescribePalletTerminal, + DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete, LocalMint, NetworkExportTableItem, NoChecking, NonFungiblesAdapter, ParentAsSuperuser, ParentIsPreset, @@ -98,7 +98,7 @@ pub type LocationToAccountId = ( AccountId32Aliases, // Foreign chain account alias into local accounts according to a hash of their standard // description. - HashedDescription>, + HashedDescription>, // Different global consensus parachain sovereign account. // (Used for over-bridge transfers and reserve processing) GlobalConsensusParachainConvertsFor, diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index a6503302a9f1..0c87a66ac1a0 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -469,7 +469,8 @@ impl pallet_glutton::Config for Runtime { } parameter_types! { - pub const PreimageHoldReason: RuntimeHoldReason = RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage); + pub const PreimageHoldReason: RuntimeHoldReason = + RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage); } impl pallet_preimage::Config for Runtime { @@ -1745,10 +1746,6 @@ impl pallet_asset_conversion::Config for Runtime { pub type NativeAndAssetsFreezer = UnionOf, AccountId>; -parameter_types! { - pub const StakingRewardsPalletId: PalletId = PalletId(*b"py/stkrd"); -} - /// Benchmark Helper #[cfg(feature = "runtime-benchmarks")] pub struct AssetRewardsBenchmarkHelper; @@ -1765,34 +1762,28 @@ impl pallet_asset_rewards::benchmarking::BenchmarkHelper> } } -/// Give Root Origin permission to create pools, and an acc id of 0. -pub struct AssetRewardsPermissionedOrigin; -impl EnsureOrigin for AssetRewardsPermissionedOrigin { - type Success = ::AccountId; - - fn try_origin(origin: RuntimeOrigin) -> Result { - match origin.clone().into() { - Ok(frame_system::RawOrigin::Root) => Ok([0u8; 32].into()), - _ => Err(origin), - } - } - - #[cfg(feature = "runtime-benchmarks")] - fn try_successful_origin() -> Result { - Ok(RuntimeOrigin::root()) - } +parameter_types! { + pub const StakingRewardsPalletId: PalletId = PalletId(*b"py/stkrd"); + pub const CreationHoldReason: RuntimeHoldReason = + RuntimeHoldReason::AssetRewards(pallet_asset_rewards::HoldReason::PoolCreation); } impl pallet_asset_rewards::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeFreezeReason = RuntimeFreezeReason; type AssetId = NativeOrWithId; - type Balance = u128; + type Balance = Balance; type Assets = NativeAndAssets; type PalletId = StakingRewardsPalletId; - type CreatePoolOrigin = AssetRewardsPermissionedOrigin; + type CreatePoolOrigin = EnsureSigned; type WeightInfo = (); type AssetsFreezer = NativeAndAssetsFreezer; + type Consideration = HoldConsideration< + AccountId, + Balances, + CreationHoldReason, + LinearStoragePrice, Balance>, + >; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = AssetRewardsBenchmarkHelper; } diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index c03cae462531..7db94d43f9e0 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -24,7 +24,7 @@ use frame_support::{ assert_ok, traits::{ fungibles::{Create, Inspect, Mutate}, - EnsureOrigin, + Consideration, EnsureOrigin, Footprint, }, }; use frame_system::{pallet_prelude::BlockNumberFor, Pallet as System, RawOrigin}; @@ -58,6 +58,9 @@ where T::CreatePoolOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let caller = T::CreatePoolOrigin::ensure_origin(caller_origin.clone()).unwrap(); + let footprint = Footprint::from_mel::<(PoolId, PoolInfoFor)>(); + T::Consideration::ensure_successful(&caller, footprint); + let staked_asset = T::BenchmarkHelper::staked_asset(); let reward_asset = T::BenchmarkHelper::reward_asset(); @@ -122,6 +125,9 @@ mod benchmarks { T::CreatePoolOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let caller = T::CreatePoolOrigin::ensure_origin(caller_origin.clone()).unwrap(); + let footprint = Footprint::from_mel::<(PoolId, PoolInfoFor)>(); + T::Consideration::ensure_successful(&caller, footprint); + let staked_asset = T::BenchmarkHelper::staked_asset(); let reward_asset = T::BenchmarkHelper::reward_asset(); diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 4c6baccf7b7b..61b8cecdcde3 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -169,6 +169,7 @@ pub mod pallet { traits::{ fungibles::MutateFreeze, tokens::{AssetId, Fortitude, Preservation}, + Consideration, Footprint, }, }; use frame_system::pallet_prelude::*; @@ -188,6 +189,14 @@ pub mod pallet { Staked, } + /// A reason for the pallet placing a hold on funds. + #[pallet::composite_enum] + pub enum HoldReason { + /// Cost associated with storing pool information on-chain. + #[codec(index = 0)] + PoolCreation, + } + #[pallet::config] pub trait Config: frame_system::Config { /// Overarching event type. @@ -226,6 +235,13 @@ pub mod pallet { /// The overarching freeze reason. type RuntimeFreezeReason: From; + /// Means for associating a cost with the on-chain storage of pool information, which + /// is incurred by the pool creator. + /// + /// The passed `Footprint` specifically accounts for the storage footprint of the pool's + /// information itself, excluding any potential storage footprint related to the stakers. + type Consideration: Consideration; + /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; @@ -249,6 +265,14 @@ pub mod pallet { #[pallet::storage] pub type Pools = StorageMap<_, Blake2_128Concat, PoolId, PoolInfoFor>; + /// The cost associated with storing pool information on-chain which was incurred by the pool + /// creator. + /// + /// This cost may be [`None`], as determined by [`Config::Consideration`]. + #[pallet::storage] + pub type PoolCost = + StorageMap<_, Blake2_128Concat, PoolId, (T::AccountId, T::Consideration)>; + /// Stores the [`PoolId`] to use for the next pool. /// /// Incremented when a new pool is created. @@ -345,6 +369,8 @@ pub mod pallet { Overflow, /// Insufficient funds to create the freeze. InsufficientFunds, + /// Pool creation cost defined by [`Config::Consideration`] is not applied. + PoolCostNotApplied, } #[pallet::hooks] @@ -399,6 +425,15 @@ pub mod pallet { Error::::ExpiryBlockMustBeInTheFuture ); + let pool_id = NextPoolId::::get(); + + let footprint = Footprint::from_mel::<(PoolId, PoolInfoFor)>(); + if let Some(cost) = T::Consideration::new(&creator, footprint) + .map_err(|_| Error::::PoolCostNotApplied)? + { + PoolCost::::insert(pool_id, (creator.clone(), cost)); + } + // Get the admin, defaulting to the origin. let admin = admin.unwrap_or(creator.clone()); @@ -415,7 +450,6 @@ pub mod pallet { }; // Insert it into storage. - let pool_id = NextPoolId::::get(); Pools::::insert(pool_id, pool); // TODO should be checked add NextPoolId::::put(pool_id.saturating_add(1)); diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index ce12cd60860f..62c6d725455e 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -18,15 +18,15 @@ //! Test environment for Asset Rewards pallet. use super::*; -use crate as pallet_staking_rewards; +use crate as pallet_asset_rewards; use core::default::Default; use frame_support::{ construct_runtime, derive_impl, instances::Instance1, parameter_types, traits::{ - tokens::fungible::{NativeFromLeft, NativeOrWithId, UnionOf}, - AsEnsureOriginWithArg, ConstU128, ConstU32, EnsureOrigin, + tokens::fungible::{HoldConsideration, NativeFromLeft, NativeOrWithId, UnionOf}, + AsEnsureOriginWithArg, ConstU128, ConstU32, EnsureOrigin, LinearStoragePrice, }, PalletId, }; @@ -45,7 +45,7 @@ construct_runtime!( Balances: pallet_balances, Assets: pallet_assets::, AssetsFreezer: pallet_assets_freezer::, - StakingRewards: pallet_staking_rewards, + StakingRewards: pallet_asset_rewards, } ); @@ -69,7 +69,7 @@ impl pallet_balances::Config for MockRuntime { type ReserveIdentifier = [u8; 8]; type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = ConstU32<50>; - type RuntimeHoldReason = (); + type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; } @@ -145,6 +145,11 @@ impl BenchmarkHelper> for AssetRewardsBenchmarkHelper { } } +parameter_types! { + pub const CreationHoldReason: RuntimeHoldReason = + RuntimeHoldReason::StakingRewards(pallet_asset_rewards::HoldReason::PoolCreation); +} + impl Config for MockRuntime { type RuntimeEvent = RuntimeEvent; type AssetId = NativeOrWithId; @@ -155,6 +160,12 @@ impl Config for MockRuntime { type CreatePoolOrigin = MockPermissionedOrigin; type WeightInfo = (); type RuntimeFreezeReason = RuntimeFreezeReason; + type Consideration = HoldConsideration< + u128, + Balances, + CreationHoldReason, + LinearStoragePrice, ConstU128<0>, u128>, + >; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = AssetRewardsBenchmarkHelper; } @@ -191,6 +202,7 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities { let pool_zero_account_id = 31086825966906540362769395565; pallet_balances::GenesisConfig:: { balances: vec![ + // (0, 10000), (1, 10000), (2, 20000), (3, 30000), diff --git a/substrate/frame/asset-rewards/src/weights.rs b/substrate/frame/asset-rewards/src/weights.rs index 09dd85e1b3ff..ade36a35797c 100644 --- a/substrate/frame/asset-rewards/src/weights.rs +++ b/substrate/frame/asset-rewards/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for `pallet_asset_rewards` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-07-29, STEPS: `50`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-07-31, STEPS: `50`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `cob`, CPU: `` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` @@ -61,76 +61,92 @@ pub trait WeightInfo { /// Weights for `pallet_asset_rewards` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { + /// Storage: `Assets::Asset` (r:2 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::NextPoolId` (r:1 w:1) /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::PoolCost` (r:0 w:1) + /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::Pools` (r:0 w:1) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn create_pool() -> Weight { // Proof Size summary in bytes: - // Measured: `109` - // Estimated: `1489` - // Minimum execution time: 116_000_000 picoseconds. - Weight::from_parts(135_000_000, 1489) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `495` + // Estimated: `6360` + // Minimum execution time: 708_000_000 picoseconds. + Weight::from_parts(779_000_000, 6360) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:1) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:0) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:0) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::Freezes` (r:1 w:1) + /// Proof: `AssetsFreezer::Freezes` (`max_values`: None, `max_size`: Some(105), added: 2580, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:1) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn stake() -> Weight { // Proof Size summary in bytes: - // Measured: `336` - // Estimated: `4764` - // Minimum execution time: 463_000_000 picoseconds. - Weight::from_parts(488_000_000, 4764) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + // Measured: `852` + // Estimated: `3675` + // Minimum execution time: 441_000_000 picoseconds. + Weight::from_parts(460_000_000, 3675) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:1) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:0) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::Freezes` (r:1 w:1) + /// Proof: `AssetsFreezer::Freezes` (`max_values`: None, `max_size`: Some(105), added: 2580, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:0) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:1) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn unstake() -> Weight { // Proof Size summary in bytes: - // Measured: `532` - // Estimated: `4764` - // Minimum execution time: 455_000_000 picoseconds. - Weight::from_parts(458_000_000, 4764) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + // Measured: `904` + // Estimated: `3599` + // Minimum execution time: 480_000_000 picoseconds. + Weight::from_parts(488_000_000, 3599) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn harvest_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `517` - // Estimated: `3593` - // Minimum execution time: 633_000_000 picoseconds. - Weight::from_parts(641_000_000, 3593) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `990` + // Estimated: `6208` + // Minimum execution time: 659_000_000 picoseconds. + Weight::from_parts(660_000_000, 6208) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn set_pool_reward_rate_per_block() -> Weight { // Proof Size summary in bytes: - // Measured: `274` + // Measured: `316` // Estimated: `3584` - // Minimum execution time: 119_000_000 picoseconds. - Weight::from_parts(123_000_000, 3584) + // Minimum execution time: 121_000_000 picoseconds. + Weight::from_parts(125_000_000, 3584) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -138,10 +154,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn set_pool_admin() -> Weight { // Proof Size summary in bytes: - // Measured: `274` + // Measured: `316` // Estimated: `3584` - // Minimum execution time: 125_000_000 picoseconds. - Weight::from_parts(141_000_000, 3584) + // Minimum execution time: 118_000_000 picoseconds. + Weight::from_parts(149_000_000, 3584) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -149,113 +165,137 @@ impl WeightInfo for SubstrateWeight { /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn set_pool_expiry_block() -> Weight { // Proof Size summary in bytes: - // Measured: `274` + // Measured: `316` // Estimated: `3584` - // Minimum execution time: 127_000_000 picoseconds. - Weight::from_parts(166_000_000, 3584) + // Minimum execution time: 124_000_000 picoseconds. + Weight::from_parts(133_000_000, 3584) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn deposit_reward_tokens() -> Weight { // Proof Size summary in bytes: - // Measured: `274` - // Estimated: `3593` - // Minimum execution time: 519_000_000 picoseconds. - Weight::from_parts(527_000_000, 3593) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `809` + // Estimated: `6208` + // Minimum execution time: 578_000_000 picoseconds. + Weight::from_parts(578_000_000, 6208) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn withdraw_reward_tokens() -> Weight { // Proof Size summary in bytes: - // Measured: `377` - // Estimated: `3593` - // Minimum execution time: 598_000_000 picoseconds. - Weight::from_parts(627_000_000, 3593) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `990` + // Estimated: `6208` + // Minimum execution time: 627_000_000 picoseconds. + Weight::from_parts(718_000_000, 6208) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } } // For backwards compatibility and tests. impl WeightInfo for () { + /// Storage: `Assets::Asset` (r:2 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::NextPoolId` (r:1 w:1) /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::PoolCost` (r:0 w:1) + /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::Pools` (r:0 w:1) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn create_pool() -> Weight { // Proof Size summary in bytes: - // Measured: `109` - // Estimated: `1489` - // Minimum execution time: 116_000_000 picoseconds. - Weight::from_parts(135_000_000, 1489) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `495` + // Estimated: `6360` + // Minimum execution time: 708_000_000 picoseconds. + Weight::from_parts(779_000_000, 6360) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:1) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:0) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:0) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::Freezes` (r:1 w:1) + /// Proof: `AssetsFreezer::Freezes` (`max_values`: None, `max_size`: Some(105), added: 2580, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:1) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn stake() -> Weight { // Proof Size summary in bytes: - // Measured: `336` - // Estimated: `4764` - // Minimum execution time: 463_000_000 picoseconds. - Weight::from_parts(488_000_000, 4764) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + // Measured: `852` + // Estimated: `3675` + // Minimum execution time: 441_000_000 picoseconds. + Weight::from_parts(460_000_000, 3675) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:1) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:0) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::Freezes` (r:1 w:1) + /// Proof: `AssetsFreezer::Freezes` (`max_values`: None, `max_size`: Some(105), added: 2580, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:0) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:1) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn unstake() -> Weight { // Proof Size summary in bytes: - // Measured: `532` - // Estimated: `4764` - // Minimum execution time: 455_000_000 picoseconds. - Weight::from_parts(458_000_000, 4764) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + // Measured: `904` + // Estimated: `3599` + // Minimum execution time: 480_000_000 picoseconds. + Weight::from_parts(488_000_000, 3599) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn harvest_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `517` - // Estimated: `3593` - // Minimum execution time: 633_000_000 picoseconds. - Weight::from_parts(641_000_000, 3593) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `990` + // Estimated: `6208` + // Minimum execution time: 659_000_000 picoseconds. + Weight::from_parts(660_000_000, 6208) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn set_pool_reward_rate_per_block() -> Weight { // Proof Size summary in bytes: - // Measured: `274` + // Measured: `316` // Estimated: `3584` - // Minimum execution time: 119_000_000 picoseconds. - Weight::from_parts(123_000_000, 3584) + // Minimum execution time: 121_000_000 picoseconds. + Weight::from_parts(125_000_000, 3584) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -263,10 +303,10 @@ impl WeightInfo for () { /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn set_pool_admin() -> Weight { // Proof Size summary in bytes: - // Measured: `274` + // Measured: `316` // Estimated: `3584` - // Minimum execution time: 125_000_000 picoseconds. - Weight::from_parts(141_000_000, 3584) + // Minimum execution time: 118_000_000 picoseconds. + Weight::from_parts(149_000_000, 3584) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -274,37 +314,45 @@ impl WeightInfo for () { /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) fn set_pool_expiry_block() -> Weight { // Proof Size summary in bytes: - // Measured: `274` + // Measured: `316` // Estimated: `3584` - // Minimum execution time: 127_000_000 picoseconds. - Weight::from_parts(166_000_000, 3584) + // Minimum execution time: 124_000_000 picoseconds. + Weight::from_parts(133_000_000, 3584) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn deposit_reward_tokens() -> Weight { // Proof Size summary in bytes: - // Measured: `274` - // Estimated: `3593` - // Minimum execution time: 519_000_000 picoseconds. - Weight::from_parts(527_000_000, 3593) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Measured: `809` + // Estimated: `6208` + // Minimum execution time: 578_000_000 picoseconds. + Weight::from_parts(578_000_000, 6208) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn withdraw_reward_tokens() -> Weight { // Proof Size summary in bytes: - // Measured: `377` - // Estimated: `3593` - // Minimum execution time: 598_000_000 picoseconds. - Weight::from_parts(627_000_000, 3593) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Measured: `990` + // Estimated: `6208` + // Minimum execution time: 627_000_000 picoseconds. + Weight::from_parts(718_000_000, 6208) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } } From 3e0fba21decd62010987976ad43951733ced1cf9 Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 31 Jul 2024 14:43:46 +0200 Subject: [PATCH 110/159] fix integration tests --- .../assets/asset-hub-rococo/src/tests/mod.rs | 2 +- ...ry_asset_reward_pool.rs => reward_pool.rs} | 50 ++++++++++++++----- .../assets/asset-hub-westend/src/tests/mod.rs | 2 +- ...ry_asset_reward_pool.rs => reward_pool.rs} | 49 +++++++++++++----- 4 files changed, 75 insertions(+), 28 deletions(-) rename cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/{treasury_asset_reward_pool.rs => reward_pool.rs} (65%) rename cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/{treasury_asset_reward_pool.rs => reward_pool.rs} (65%) diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs index 510935777bd3..75714acb07cd 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/mod.rs @@ -16,10 +16,10 @@ mod claim_assets; mod hybrid_transfers; mod reserve_transfer; +mod reward_pool; mod send; mod set_xcm_versions; mod swap; mod teleport; mod treasury; -mod treasury_asset_reward_pool; mod xcm_fee_estimation; diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reward_pool.rs similarity index 65% rename from cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs rename to cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reward_pool.rs index 677399ed4aab..647a15e41074 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/treasury_asset_reward_pool.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reward_pool.rs @@ -17,9 +17,33 @@ use crate::imports::*; use codec::Encode; use emulated_integration_tests_common::ASSET_HUB_ROCOCO_ID; use frame_support::{assert_ok, sp_runtime::traits::Dispatchable}; +use xcm_executor::traits::ConvertLocation; #[test] fn treasury_creates_asset_reward_pool() { + AssetHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type Balances = ::Balances; + + let treasurer = + Location::new(1, [Plurality { id: BodyId::Treasury, part: BodyPart::Voice }]); + let treasurer_account = + ahr_xcm_config::LocationToAccountId::convert_location(&treasurer).unwrap(); + + assert_ok!(Balances::force_set_balance( + ::RuntimeOrigin::root(), + treasurer_account.clone().into(), + ASSET_HUB_ROCOCO_ED * 100_000, + )); + + let events = AssetHubRococo::events(); + match events.iter().last() { + Some(RuntimeEvent::Balances(pallet_balances::Event::BalanceSet { who, .. })) => + assert_eq!(*who, treasurer_account), + _ => panic!("Expected Balances::BalanceSet event"), + } + }); + Rococo::execute_with(|| { type AssetHubRococoRuntimeCall = ::RuntimeCall; type AssetHubRococoRuntime = ::Runtime; @@ -43,7 +67,7 @@ fn treasury_creates_asset_reward_pool() { message: bx!(VersionedXcm::V4(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { - origin_kind: OriginKind::Xcm, + origin_kind: OriginKind::SovereignAccount, require_weight_at_most: Weight::from_parts(5_000_000_000, 500_000), call: AssetHubRococoRuntimeCall::AssetRewards( pallet_asset_rewards::Call::::create_pool { @@ -72,18 +96,18 @@ fn treasury_creates_asset_reward_pool() { }); AssetHubRococo::execute_with(|| { - type AssetHubRococoRuntimeEvent = ::RuntimeEvent; - assert_expected_events!( - AssetHubRococo, - vec![ - AssetHubRococoRuntimeEvent::AssetRewards( - pallet_asset_rewards::Event::PoolCreated { - .. - } - ) => { - }, + type Runtime = ::Runtime; + type RuntimeEvent = ::RuntimeEvent; - ] - ); + assert_eq!(1, pallet_asset_rewards::Pools::::iter().count()); + + let events = AssetHubRococo::events(); + match events.iter().last() { + Some(RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { + success: true, + .. + })) => (), + _ => panic!("Expected MessageQueue::Processed event"), + } }); } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs index 2394513a399c..151b6556afee 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs @@ -17,10 +17,10 @@ mod claim_assets; mod fellowship_treasury; mod hybrid_transfers; mod reserve_transfer; +mod reward_pool; mod send; mod set_xcm_versions; mod swap; mod teleport; mod treasury; -mod treasury_asset_reward_pool; mod xcm_fee_estimation; diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reward_pool.rs similarity index 65% rename from cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs rename to cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reward_pool.rs index 0d7da6faf322..4b512d75457c 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/treasury_asset_reward_pool.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reward_pool.rs @@ -17,9 +17,32 @@ use crate::imports::*; use codec::Encode; use emulated_integration_tests_common::ASSET_HUB_WESTEND_ID; use frame_support::{assert_ok, sp_runtime::traits::Dispatchable}; +use xcm_executor::traits::ConvertLocation; #[test] fn treasury_creates_asset_reward_pool() { + AssetHubWestend::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type Balances = ::Balances; + + let treasurer = + Location::new(1, [Plurality { id: BodyId::Treasury, part: BodyPart::Voice }]); + let treasurer_account = + ahw_xcm_config::LocationToAccountId::convert_location(&treasurer).unwrap(); + + assert_ok!(Balances::force_set_balance( + ::RuntimeOrigin::root(), + treasurer_account.clone().into(), + ASSET_HUB_WESTEND_ED * 100_000, + )); + + let events = AssetHubWestend::events(); + match events.iter().last() { + Some(RuntimeEvent::Balances(pallet_balances::Event::BalanceSet { who, .. })) => + assert_eq!(*who, treasurer_account), + _ => panic!("Expected Balances::BalanceSet event"), + } + }); Westend::execute_with(|| { type AssetHubWestendRuntimeCall = ::RuntimeCall; type AssetHubWestendRuntime = ::Runtime; @@ -43,7 +66,7 @@ fn treasury_creates_asset_reward_pool() { message: bx!(VersionedXcm::V4(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, Transact { - origin_kind: OriginKind::Xcm, + origin_kind: OriginKind::SovereignAccount, require_weight_at_most: Weight::from_parts(5_000_000_000, 500_000), call: AssetHubWestendRuntimeCall::AssetRewards( pallet_asset_rewards::Call::::create_pool { @@ -72,18 +95,18 @@ fn treasury_creates_asset_reward_pool() { }); AssetHubWestend::execute_with(|| { - type AssetHubWestendRuntimeEvent = ::RuntimeEvent; - assert_expected_events!( - AssetHubWestend, - vec![ - AssetHubWestendRuntimeEvent::AssetRewards( - pallet_asset_rewards::Event::PoolCreated { - .. - } - ) => { - }, + type Runtime = ::Runtime; + type RuntimeEvent = ::RuntimeEvent; - ] - ); + assert_eq!(1, pallet_asset_rewards::Pools::::iter().count()); + + let events = AssetHubWestend::events(); + match events.iter().last() { + Some(RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { + success: true, + .. + })) => (), + _ => panic!("Expected MessageQueue::Processed event"), + } }); } From 9250133cd819eeb8d70e60f6f952244864f9823a Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 31 Jul 2024 15:00:21 +0200 Subject: [PATCH 111/159] remove unused imports --- .../assets/asset-hub-rococo/src/lib.rs | 8 +++----- .../assets/asset-hub-westend/src/lib.rs | 18 ++++++++---------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 10c13ee8d1bb..6b9c7ebad689 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -47,7 +47,6 @@ use sp_runtime::{ ApplyExtrinsicResult, Permill, }; use testnet_parachains_constants::rococo::snowbridge::EthereumNetwork; -use xcm_executor::traits::ConvertLocation; #[cfg(feature = "std")] use sp_version::NativeVersion; @@ -72,7 +71,7 @@ use frame_support::{ }; use frame_system::{ limits::{BlockLength, BlockWeights}, - EnsureRoot, EnsureSigned, EnsureSignedBy, EnsureWithSuccess, + EnsureRoot, EnsureSigned, EnsureSignedBy, }; use pallet_asset_conversion_tx_payment::SwapAssetAdapter; use pallet_nfts::PalletFeatures; @@ -86,9 +85,8 @@ use sp_runtime::{Perbill, RuntimeDebug}; use testnet_parachains_constants::rococo::{consensus::*, currency::*, fee::WeightToFee, time::*}; use xcm_config::{ ForeignAssetsConvertedConcreteId, ForeignCreatorsSovereignAccountOf, GovernanceLocation, - LocationToAccountId, PoolAssetsConvertedConcreteId, PoolAssetsPalletLocationV3, - RelayTreasuryLocation, TokenLocation, TokenLocationV3, TrustBackedAssetsConvertedConcreteId, - TrustBackedAssetsPalletLocationV3, + PoolAssetsConvertedConcreteId, PoolAssetsPalletLocationV3, TokenLocation, TokenLocationV3, + TrustBackedAssetsConvertedConcreteId, TrustBackedAssetsPalletLocationV3, }; #[cfg(any(feature = "std", test))] 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 c9566818dd98..ee3166ec6970 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -47,19 +47,19 @@ use frame_support::{ fungible::HoldConsideration, fungibles, tokens::{imbalance::ResolveAssetTo, nonfungibles_v2::Inspect}, - AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, EitherOfDiverse, - Equals, InstanceFilter, LinearStoragePrice, TransformOrigin, + AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Equals, + InstanceFilter, LinearStoragePrice, TransformOrigin, }, weights::{ConstantMultiplier, Weight, WeightToFee as _}, BoundedVec, PalletId, }; use frame_system::{ limits::{BlockLength, BlockWeights}, - EnsureRoot, EnsureSigned, EnsureSignedBy, EnsureWithSuccess, + EnsureRoot, EnsureSigned, EnsureSignedBy, }; use pallet_asset_conversion_tx_payment::SwapAssetAdapter; use pallet_nfts::{DestroyWitness, PalletFeatures}; -use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; +use pallet_xcm::EnsureXcm; use parachains_common::{ impls::DealWithFees, message_queue::*, AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, CollectionId, Hash, Header, ItemId, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, @@ -78,12 +78,11 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; use testnet_parachains_constants::westend::{consensus::*, currency::*, fee::WeightToFee, time::*}; use xcm_config::{ - ForeignAssetsConvertedConcreteId, ForeignCreatorsSovereignAccountOf, GovernanceLocation, - LocationToAccountId, PoolAssetsConvertedConcreteId, PoolAssetsPalletLocationV3, - RelayTreasuryLocation, TrustBackedAssetsConvertedConcreteId, TrustBackedAssetsPalletLocationV3, - WestendLocation, WestendLocationV3, XcmOriginToTransactDispatchOrigin, + ForeignAssetsConvertedConcreteId, ForeignCreatorsSovereignAccountOf, + PoolAssetsConvertedConcreteId, PoolAssetsPalletLocationV3, + TrustBackedAssetsConvertedConcreteId, TrustBackedAssetsPalletLocationV3, WestendLocation, + WestendLocationV3, XcmOriginToTransactDispatchOrigin, }; -use xcm_executor::traits::ConvertLocation; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; @@ -93,7 +92,6 @@ use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; use xcm::{ latest::prelude::AssetId, - lts::BodyId, prelude::{VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm}, }; From 656d501884b18a2e81e22de802febcead39fb75b Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 31 Jul 2024 15:06:32 +0200 Subject: [PATCH 112/159] remove duplication from wrokspace members list --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index fd68b6c6b50f..460050d53227 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -311,7 +311,6 @@ members = [ "substrate/frame/asset-conversion/ops", "substrate/frame/asset-rate", "substrate/frame/asset-rewards", - "substrate/frame/asset-rewards", "substrate/frame/assets", "substrate/frame/assets-freezer", "substrate/frame/atomic-swap", From 5fcee69c222596d94fc78cede680a370bcdf16af Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 31 Jul 2024 15:11:35 +0200 Subject: [PATCH 113/159] taplo format --- substrate/frame/asset-rewards/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/frame/asset-rewards/Cargo.toml b/substrate/frame/asset-rewards/Cargo.toml index 3df2adea28fb..053e9824978c 100644 --- a/substrate/frame/asset-rewards/Cargo.toml +++ b/substrate/frame/asset-rewards/Cargo.toml @@ -56,16 +56,16 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-assets-freezer/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "sp-runtime/runtime-benchmarks", - "pallet-assets-freezer/runtime-benchmarks" ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "pallet-assets-freezer/try-runtime", "pallet-assets/try-runtime", "pallet-balances/try-runtime", "sp-runtime/try-runtime", - "pallet-assets-freezer/try-runtime" ] From 196e6c42cff88325100c5e6eb75456ab32ba5359 Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 31 Jul 2024 15:12:36 +0200 Subject: [PATCH 114/159] remove unused imports --- substrate/bin/node/runtime/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 0c87a66ac1a0..2da06f2be9b5 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -50,9 +50,9 @@ use frame_support::{ GetSalary, PayFromAccount, }, AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU16, ConstU32, Contains, Currency, - EitherOfDiverse, EnsureOrigin, EnsureOriginWithArg, EqualPrivilegeOnly, Imbalance, - InsideBoth, InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, LockIdentifier, - Nothing, OnUnbalanced, VariantCountOf, WithdrawReasons, + EitherOfDiverse, EnsureOriginWithArg, EqualPrivilegeOnly, Imbalance, InsideBoth, + InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, LockIdentifier, Nothing, + OnUnbalanced, VariantCountOf, WithdrawReasons, }, weights::{ constants::{ From dec45b3160716c7378508d0d870e546b429db61e Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 31 Jul 2024 15:20:25 +0200 Subject: [PATCH 115/159] fix umbrella crate inclusion order --- substrate/frame/asset-rewards/Cargo.toml | 2 +- umbrella/src/lib.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/substrate/frame/asset-rewards/Cargo.toml b/substrate/frame/asset-rewards/Cargo.toml index 053e9824978c..99945b0ec19a 100644 --- a/substrate/frame/asset-rewards/Cargo.toml +++ b/substrate/frame/asset-rewards/Cargo.toml @@ -6,7 +6,7 @@ edition.workspace = true license = "Apache-2.0" homepage = "https://substrate.io" repository.workspace = true -description = "FRAME staking rewards pallet" +description = "FRAME asset rewards pallet" readme = "README.md" [lints] diff --git a/umbrella/src/lib.rs b/umbrella/src/lib.rs index 3552536258d9..2b00b09c2ca1 100644 --- a/umbrella/src/lib.rs +++ b/umbrella/src/lib.rs @@ -340,10 +340,6 @@ pub use pallet_alliance; #[cfg(feature = "pallet-asset-conversion")] pub use pallet_asset_conversion; -/// FRAME asset conversion pallet. -#[cfg(feature = "pallet-asset-rewards")] -pub use pallet_asset_rewards; - /// FRAME asset conversion pallet's operations suite. #[cfg(feature = "pallet-asset-conversion-ops")] pub use pallet_asset_conversion_ops; @@ -356,6 +352,10 @@ pub use pallet_asset_conversion_tx_payment; #[cfg(feature = "pallet-asset-rate")] pub use pallet_asset_rate; +/// FRAME asset rewards pallet. +#[cfg(feature = "pallet-asset-rewards")] +pub use pallet_asset_rewards; + /// pallet to manage transaction payments in assets. #[cfg(feature = "pallet-asset-tx-payment")] pub use pallet_asset_tx_payment; From 78fa44ed7a25920b8cd33df03583f9426c0cf4ae Mon Sep 17 00:00:00 2001 From: muharem Date: Thu, 1 Aug 2024 10:47:24 +0200 Subject: [PATCH 116/159] mock: fund root account for pool deposit --- substrate/frame/asset-rewards/src/mock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index 62c6d725455e..e17cd035f456 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -202,7 +202,7 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities { let pool_zero_account_id = 31086825966906540362769395565; pallet_balances::GenesisConfig:: { balances: vec![ - // (0, 10000), + (0, 10000), (1, 10000), (2, 20000), (3, 30000), From c4ff4204ba19b6112b308a1e772846c8e314b458 Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 7 Aug 2024 14:09:12 +0200 Subject: [PATCH 117/159] pool admin is not optional --- .../frame/asset-rewards/src/benchmarking.rs | 6 +-- substrate/frame/asset-rewards/src/lib.rs | 38 ++++++++----------- substrate/frame/asset-rewards/src/mock.rs | 3 +- substrate/frame/asset-rewards/src/tests.rs | 24 ++++++------ 4 files changed, 31 insertions(+), 40 deletions(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 7db94d43f9e0..029c2e307376 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -153,7 +153,7 @@ mod benchmarks { assert_last_event::( Event::PoolCreated { creator: caller.clone(), - admin: Some(caller), + admin: caller, staked_asset_id: staked_asset, reward_asset_id: reward_asset, reward_rate_per_block: min_balance, @@ -263,9 +263,7 @@ mod benchmarks { #[extrinsic_call] _(caller_origin as T::RuntimeOrigin, 0, new_admin.clone()); - assert_last_event::( - Event::PoolAdminModified { pool_id: 0, new_admin: Some(new_admin) }.into(), - ); + assert_last_event::(Event::PoolAdminModified { pool_id: 0, new_admin }.into()); Ok(()) } diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 61b8cecdcde3..16ec63d6fcfc 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -21,11 +21,10 @@ //! //! ## Overview //! -//! A permissioned origin can initiate an incentive program for a fungible asset by creating a new -//! pool. +//! Initiate an incentive program for a fungible asset by creating a new pool. //! //! During pool creation, a 'staking asset', 'reward asset', 'reward rate per block', 'expiry -//! block', and 'admin' are specified. By default, the permissioned origin is the admin. +//! block', and 'admin' are specified. //! //! Once created, holders of the 'staking asset' can 'stake' them in a corresponding pool, which //! creates a Freeze on the asset. @@ -148,11 +147,8 @@ pub struct PoolInfo { reward_rate_per_block: Balance, /// The block the pool will cease distributing rewards. expiry_block: BlockNumber, - /// The permissioned account that can manage this pool. - /// - /// This is currently always `Some`, and only an `Option` so in the future permissionless - /// pools may be enabled without storage migration. - admin: Option, + /// The account that can manage this pool. + admin: AccountId, /// The total amount of tokens staked in this pool. total_tokens_staked: Balance, /// Total rewards accumulated per token, up to the `last_update_block`. @@ -212,11 +208,9 @@ pub mod pallet { /// The type in which the assets are measured. type Balance: Balance + TypeInfo; - /// The origin with permission to create pools. This will be removed in a later release of - /// this pallet, which will allow permissionless pool creation. + /// The origin with permission to create pools. /// - /// The Origin must return an AccountId. This can be achieved for any Origin by wrapping it - /// with `EnsureSuccess`. + /// The Origin must return an AccountId. type CreatePoolOrigin: EnsureOrigin; /// Registry of assets that can be configured to either stake for rewards, or be offered as @@ -326,7 +320,7 @@ pub mod pallet { /// The block the pool will cease to accumulate rewards. expiry_block: BlockNumberFor, /// The account allowed to modify the pool. - admin: Option, + admin: T::AccountId, }, /// A pool reward rate was modified by the admin. PoolRewardRateModified { @@ -340,7 +334,7 @@ pub mod pallet { /// The modified pool. pool_id: PoolId, /// The new admin. - new_admin: Option, + new_admin: T::AccountId, }, /// A pool expiry block was modified by the admin. PoolExpiryBlockModified { @@ -446,7 +440,7 @@ pub mod pallet { reward_per_token_stored: 0u32.into(), last_update_block: 0u32.into(), expiry_block, - admin: Some(admin.clone()), + admin: admin.clone(), }; // Insert it into storage. @@ -462,7 +456,7 @@ pub mod pallet { reward_asset_id: *reward_asset_id, reward_rate_per_block, expiry_block, - admin: Some(admin), + admin, }); Ok(()) @@ -623,7 +617,7 @@ pub mod pallet { .or_else(|_| ensure_signed(origin))?; let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(Some(caller) == pool_info.admin, BadOrigin); + ensure!(caller == pool_info.admin, BadOrigin); // Always start by updating the pool rewards. let rewards_per_token = Self::reward_per_token(&pool_info)?; @@ -653,11 +647,11 @@ pub mod pallet { .or_else(|_| ensure_signed(origin))?; let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin == Some(caller), BadOrigin); - pool_info.admin = Some(new_admin.clone()); + ensure!(pool_info.admin == caller, BadOrigin); + pool_info.admin = new_admin.clone(); Pools::::insert(pool_id, pool_info); - Self::deposit_event(Event::PoolAdminModified { pool_id, new_admin: Some(new_admin) }); + Self::deposit_event(Event::PoolAdminModified { pool_id, new_admin }); Ok(()) } @@ -680,7 +674,7 @@ pub mod pallet { ); let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin == Some(caller), BadOrigin); + ensure!(pool_info.admin == caller, BadOrigin); // Always start by updating the pool rewards. let reward_per_token = Self::reward_per_token(&pool_info)?; @@ -732,7 +726,7 @@ pub mod pallet { .or_else(|_| ensure_signed(origin))?; let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin == Some(caller), BadOrigin); + ensure!(pool_info.admin == caller, BadOrigin); T::Assets::transfer( pool_info.reward_asset_id, diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index e17cd035f456..57480c4c4cba 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -122,8 +122,7 @@ impl EnsureOrigin for MockPermissionedOrigin { } /// Allow Freezes for the `Assets` pallet -pub type AssetsFreezerInstance = pallet_assets_freezer::Instance1; -impl pallet_assets_freezer::Config for MockRuntime { +impl pallet_assets_freezer::Config for MockRuntime { type RuntimeFreezeReason = RuntimeFreezeReason; type RuntimeEvent = RuntimeEvent; } diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 3758dce2975a..7674c1c4237b 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -142,7 +142,7 @@ mod create_pool { reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: expected_expiry_block, - admin: Some(PermissionedAccountId::get()), + admin: PermissionedAccountId::get(), }] ); @@ -157,7 +157,7 @@ mod create_pool { reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: expected_expiry_block, - admin: Some(PermissionedAccountId::get()), + admin: PermissionedAccountId::get(), total_tokens_staked: 0, reward_per_token_stored: 0, last_update_block: 0 @@ -190,7 +190,7 @@ mod create_pool { staked_asset_id: staked_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, - admin: Some(admin), + admin, expiry_block: expected_expiry_block, }] ); @@ -206,7 +206,7 @@ mod create_pool { staked_asset_id: DEFAULT_STAKED_ASSET_ID, reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, - admin: Some(PermissionedAccountId::get()), + admin: PermissionedAccountId::get(), expiry_block: DEFAULT_LIFETIME + 10, total_tokens_staked: 0, reward_per_token_stored: 0, @@ -219,7 +219,7 @@ mod create_pool { staked_asset_id, reward_asset_id, reward_rate_per_block, - admin: Some(admin), + admin, total_tokens_staked: 0, expiry_block: expected_expiry_block, reward_per_token_stored: 0, @@ -260,7 +260,7 @@ mod create_pool { reward_asset_id: asset.clone(), reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: expected_expiry_block, - admin: Some(PermissionedAccountId::get()), + admin: PermissionedAccountId::get(), }] ); @@ -275,7 +275,7 @@ mod create_pool { reward_asset_id: asset, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: expected_expiry_block, - admin: Some(PermissionedAccountId::get()), + admin: PermissionedAccountId::get(), total_tokens_staked: 0, reward_per_token_stored: 0, last_update_block: 0 @@ -671,9 +671,9 @@ mod set_pool_admin { // Check state assert_eq!( *events().last().unwrap(), - Event::::PoolAdminModified { pool_id, new_admin: Some(new_admin) } + Event::::PoolAdminModified { pool_id, new_admin } ); - assert_eq!(Pools::::get(pool_id).unwrap().admin, Some(new_admin)); + assert_eq!(Pools::::get(pool_id).unwrap().admin, new_admin); }); } @@ -690,9 +690,9 @@ mod set_pool_admin { // Check state assert_eq!( *events().last().unwrap(), - Event::::PoolAdminModified { pool_id, new_admin: Some(new_admin) } + Event::::PoolAdminModified { pool_id, new_admin } ); - assert_eq!(Pools::::get(pool_id).unwrap().admin, Some(new_admin)); + assert_eq!(Pools::::get(pool_id).unwrap().admin, new_admin); }); } @@ -1408,7 +1408,7 @@ fn integration() { reward_asset_id, reward_rate_per_block: 100, expiry_block: 25, - admin: Some(admin) + admin }, Event::Staked { caller: staker1, pool_id, amount: 100 }, Event::Staked { caller: staker2, pool_id, amount: 100 }, From cf8fdf3f15872bdf546a9d5f9fdd0123d3176b11 Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 7 Aug 2024 14:10:54 +0200 Subject: [PATCH 118/159] checked add on pool id increment --- substrate/frame/asset-rewards/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 16ec63d6fcfc..4a39106b02ef 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -445,8 +445,8 @@ pub mod pallet { // Insert it into storage. Pools::::insert(pool_id, pool); - // TODO should be checked add - NextPoolId::::put(pool_id.saturating_add(1)); + + NextPoolId::::put(pool_id.checked_add(1).ok_or(Error::::Overflow)?); // Emit created event. Self::deposit_event(Event::PoolCreated { From 264bcb46159d4c88703a55948d9cae33109f1b7e Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 7 Aug 2024 14:20:12 +0200 Subject: [PATCH 119/159] use fungible::increase_frozen --- substrate/frame/asset-rewards/src/lib.rs | 24 +++------------------- substrate/frame/asset-rewards/src/tests.rs | 2 +- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 4a39106b02ef..378dee47f3dd 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -82,7 +82,6 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::traits::fungibles::InspectFreeze; use frame_system::pallet_prelude::BlockNumberFor; pub use pallet::*; @@ -164,7 +163,7 @@ pub mod pallet { pallet_prelude::*, traits::{ fungibles::MutateFreeze, - tokens::{AssetId, Fortitude, Preservation}, + tokens::{AssetId, Preservation}, Consideration, Footprint, }, }; @@ -475,28 +474,11 @@ pub mod pallet { let (mut pool_info, mut staker_info) = Self::update_pool_and_staker_rewards(&pool_info, &staker_info)?; - // Try to freeze the staker assets. - let reducible_balance = T::Assets::reducible_balance( - pool_info.staked_asset_id.clone(), - &caller, - Preservation::Expendable, - Fortitude::Force, - ); - - ensure!(reducible_balance >= amount, Error::::InsufficientFunds); - - // Can't use `extend_frozen` because it takes the max of the current and new - // amount instead of summing them. - let prev_frozen = T::AssetsFreezer::balance_frozen( + T::AssetsFreezer::increase_frozen( pool_info.staked_asset_id.clone(), &FreezeReason::Staked.into(), &caller, - ); - T::AssetsFreezer::set_freeze( - pool_info.staked_asset_id.clone(), - &FreezeReason::Staked.into(), - &caller, - prev_frozen.checked_add(&amount).ok_or(Error::::Overflow)?, + amount, )?; // Update Pools. diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 7674c1c4237b..8014703a511f 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -451,7 +451,7 @@ mod stake { ); assert_err!( StakingRewards::stake(RuntimeOrigin::signed(user), pool_id, initial_balance + 1), - Error::::InsufficientFunds + TokenError::FundsUnavailable, ); }) } From 3d9b058b3963f0c55d95c2929bd87d0f0bac0d48 Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 7 Aug 2024 14:30:17 +0200 Subject: [PATCH 120/159] runtime api to query the pool creation cost --- substrate/frame/asset-rewards/src/lib.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 378dee47f3dd..87aa0d4382d0 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -85,6 +85,7 @@ use codec::{Decode, Encode, MaxEncodedLen}; use frame_system::pallet_prelude::BlockNumberFor; pub use pallet::*; +use codec::Codec; use frame_support::{ traits::{ fungibles::{Inspect, Mutate}, @@ -95,7 +96,7 @@ use frame_support::{ use scale_info::TypeInfo; use sp_core::Get; use sp_runtime::{ - traits::{CheckedAdd, Zero}, + traits::{CheckedAdd, MaybeDisplay, Zero}, DispatchError, }; use sp_std::boxed::Box; @@ -156,6 +157,16 @@ pub struct PoolInfo { last_update_block: BlockNumber, } +sp_api::decl_runtime_apis! { + /// The runtime API for the asset rewards pallet. + pub trait AssetRewards { + /// Get the cost of creating a pool. + /// + /// This is especially useful when the cost is dynamic. + fn pool_creation_cost() -> Cost; + } +} + #[frame_support::pallet] pub mod pallet { use super::*; @@ -420,7 +431,7 @@ pub mod pallet { let pool_id = NextPoolId::::get(); - let footprint = Footprint::from_mel::<(PoolId, PoolInfoFor)>(); + let footprint = Self::pool_creation_footprint(); if let Some(cost) = T::Consideration::new(&creator, footprint) .map_err(|_| Error::::PoolCostNotApplied)? { @@ -724,6 +735,14 @@ pub mod pallet { } impl Pallet { + /// The pool creation footprint. + /// + /// The footprint specifically accounts for the storage footprint of the pool's information + /// itself, excluding any potential storage footprint related to the stakers. + pub fn pool_creation_footprint() -> Footprint { + Footprint::from_mel::<(PoolId, PoolInfoFor)>() + } + /// Derive a pool account ID from the pallet's ID. pub fn pool_account_id(id: &PoolId) -> Result { if Pools::::contains_key(id) { From d233e3594240f877715fce953f163456578fdbd4 Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 7 Aug 2024 14:42:43 +0200 Subject: [PATCH 121/159] prdoc --- prdoc/pr_3926.prdoc | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 prdoc/pr_3926.prdoc diff --git a/prdoc/pr_3926.prdoc b/prdoc/pr_3926.prdoc new file mode 100644 index 000000000000..03f8edfbd73f --- /dev/null +++ b/prdoc/pr_3926.prdoc @@ -0,0 +1,26 @@ +title: Introduce pallet-asset-rewards + +doc: + - audience: Runtime Dev + description: | + Introduce pallet-asset-rewards, which allows accounts to be rewarded for freezing fungible + tokens. The motivation for creating this pallet is to allow incentivising LPs. + See the pallet docs for more info about the pallet. + +crates: + - name: pallet-asset-rewards + bump: major + - name: polkadot-sdk + bump: major + - name: kitchensink-runtime + bump: major + - name: asset-hub-rococo-runtime + bump: major + - name: asset-hub-westend-runtime + bump: major + - name: assets-common + bump: minor + - name: rococo-runtime + bump: minor + - name: westend-runtime + bump: minor \ No newline at end of file From 41d6e444c2b418447f4fbd52c55a1e704ed59b4a Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 7 Aug 2024 14:47:07 +0200 Subject: [PATCH 122/159] update cargo toml --- Cargo.lock | 2 +- substrate/frame/asset-rewards/Cargo.toml | 33 ++++++++++++------------ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76f4eaf2b869..69279745c454 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9830,7 +9830,7 @@ dependencies = [ [[package]] name = "pallet-asset-rewards" -version = "1.0.0" +version = "0.1.0" dependencies = [ "frame-benchmarking", "frame-support", diff --git a/substrate/frame/asset-rewards/Cargo.toml b/substrate/frame/asset-rewards/Cargo.toml index 99945b0ec19a..297d67863a7e 100644 --- a/substrate/frame/asset-rewards/Cargo.toml +++ b/substrate/frame/asset-rewards/Cargo.toml @@ -1,13 +1,12 @@ [package] name = "pallet-asset-rewards" -version = "1.0.0" +version = "0.1.0" authors.workspace = true edition.workspace = true license = "Apache-2.0" homepage = "https://substrate.io" repository.workspace = true description = "FRAME asset rewards pallet" -readme = "README.md" [lints] workspace = true @@ -16,23 +15,23 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } -frame-support = { path = "../support", default-features = false, features = ["experimental"] } -frame-system = { path = "../system", default-features = false } -frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -sp-api = { path = "../../primitives/api", default-features = false } -sp-core = { path = "../../primitives/core", default-features = false } -sp-io = { path = "../../primitives/io", default-features = false } -sp-std = { path = "../../primitives/std", default-features = false } -sp-runtime = { path = "../../primitives/runtime", default-features = false } -sp-arithmetic = { path = "../../primitives/arithmetic", default-features = false } +codec = { workspace = true, default-features = false } +frame-support = { workspace = true, default-features = false, features = ["experimental"] } +frame-system = { workspace = true, default-features = false } +frame-benchmarking = { workspace = true, default-features = false, optional = true } +scale-info = { workspace = true, default-features = false, features = ["derive"] } +sp-api = { workspace = true, default-features = false } +sp-core = { workspace = true, default-features = false } +sp-io = { workspace = true, default-features = false } +sp-std = { workspace = true, default-features = false } +sp-runtime = { workspace = true, default-features = false } +sp-arithmetic = { workspace = true, default-features = false } [dev-dependencies] -pallet-balances = { path = "../balances" } -pallet-assets = { path = "../assets" } -pallet-assets-freezer = { path = "../assets-freezer" } -primitive-types = { version = "0.12.0", default-features = false, features = ["codec", "num-traits", "scale-info"] } +pallet-balances = { workspace = true } +pallet-assets = { workspace = true } +pallet-assets-freezer = { workspace = true } +primitive-types = { workspace = true, default-features = false, features = ["codec", "num-traits", "scale-info"] } [features] default = ["std"] From 99ec6ba776ec92f7f042d4643737a07b8d53e3bf Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 7 Aug 2024 15:17:24 +0200 Subject: [PATCH 123/159] propogate std feature for pallet-assets-freezer --- substrate/frame/asset-rewards/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/substrate/frame/asset-rewards/Cargo.toml b/substrate/frame/asset-rewards/Cargo.toml index 297d67863a7e..3c29354b7bc3 100644 --- a/substrate/frame/asset-rewards/Cargo.toml +++ b/substrate/frame/asset-rewards/Cargo.toml @@ -40,6 +40,7 @@ std = [ "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-assets-freezer/std", "pallet-assets/std", "pallet-balances/std", "primitive-types/std", From 1cb24288c08df6dabcf64dfc051ad031df572075 Mon Sep 17 00:00:00 2001 From: muharem Date: Thu, 15 Aug 2024 14:44:22 +0200 Subject: [PATCH 124/159] not optional consideration --- substrate/frame/asset-rewards/src/lib.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 87aa0d4382d0..7062463a6d26 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -373,8 +373,6 @@ pub mod pallet { Overflow, /// Insufficient funds to create the freeze. InsufficientFunds, - /// Pool creation cost defined by [`Config::Consideration`] is not applied. - PoolCostNotApplied, } #[pallet::hooks] @@ -432,11 +430,8 @@ pub mod pallet { let pool_id = NextPoolId::::get(); let footprint = Self::pool_creation_footprint(); - if let Some(cost) = T::Consideration::new(&creator, footprint) - .map_err(|_| Error::::PoolCostNotApplied)? - { - PoolCost::::insert(pool_id, (creator.clone(), cost)); - } + let cost = T::Consideration::new(&creator, footprint)?; + PoolCost::::insert(pool_id, (creator.clone(), cost)); // Get the admin, defaulting to the origin. let admin = admin.unwrap_or(creator.clone()); From 00a17f6415d0dc967651a3849be83c8f0b7432a0 Mon Sep 17 00:00:00 2001 From: Muharem Date: Wed, 28 Aug 2024 15:42:46 +0200 Subject: [PATCH 125/159] Apply suggestions from code review Co-authored-by: Oliver Tale-Yazdi --- prdoc/pr_3926.prdoc | 2 +- substrate/frame/asset-rewards/Cargo.toml | 2 +- substrate/frame/asset-rewards/src/lib.rs | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/prdoc/pr_3926.prdoc b/prdoc/pr_3926.prdoc index 03f8edfbd73f..ec292b5d052c 100644 --- a/prdoc/pr_3926.prdoc +++ b/prdoc/pr_3926.prdoc @@ -23,4 +23,4 @@ crates: - name: rococo-runtime bump: minor - name: westend-runtime - bump: minor \ No newline at end of file + bump: minor diff --git a/substrate/frame/asset-rewards/Cargo.toml b/substrate/frame/asset-rewards/Cargo.toml index 3c29354b7bc3..da73ab126021 100644 --- a/substrate/frame/asset-rewards/Cargo.toml +++ b/substrate/frame/asset-rewards/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors.workspace = true edition.workspace = true license = "Apache-2.0" -homepage = "https://substrate.io" +homepage.workspace = true repository.workspace = true description = "FRAME asset rewards pallet" diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 7062463a6d26..26514c6e7327 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -265,7 +265,7 @@ pub mod pallet { PoolStakerInfo, >; - /// State and configuraiton of each staking pool. + /// State and configuration of each staking pool. #[pallet::storage] pub type Pools = StorageMap<_, Blake2_128Concat, PoolId, PoolInfoFor>; @@ -644,7 +644,7 @@ pub mod pallet { Ok(()) } - /// Modify a expiry block. + /// Set when the pool should expire. /// /// Only the pool admin may perform this operation. #[pallet::call_index(6)] @@ -676,7 +676,7 @@ pub mod pallet { Ok(()) } - /// Convinience method to deposit reward tokens into a pool. + /// Convenience method to deposit reward tokens into a pool. /// /// This method is not strictly necessary (tokens could be transferred directly to the /// pool pot address), but is provided for convenience so manual derivation of the @@ -738,7 +738,7 @@ pub mod pallet { Footprint::from_mel::<(PoolId, PoolInfoFor)>() } - /// Derive a pool account ID from the pallet's ID. + /// Derive a pool account ID from the pool's ID. pub fn pool_account_id(id: &PoolId) -> Result { if Pools::::contains_key(id) { Ok(T::PalletId::get().into_sub_account_truncating(id)) From 56774712c663bea6f3b7d098296c55b798b81367 Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 28 Aug 2024 16:02:12 +0200 Subject: [PATCH 126/159] only staker can harvest rewards --- .../frame/asset-rewards/src/benchmarking.rs | 10 +-- substrate/frame/asset-rewards/src/lib.rs | 35 ++++------- substrate/frame/asset-rewards/src/tests.rs | 62 ++----------------- 3 files changed, 18 insertions(+), 89 deletions(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 029c2e307376..0f4ca7767464 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -226,16 +226,10 @@ mod benchmarks { ); #[extrinsic_call] - _(RawOrigin::Signed(staker.clone()), 0, None); + _(RawOrigin::Signed(staker.clone()), 0); assert_last_event::( - Event::RewardsHarvested { - caller: staker.clone(), - staker, - pool_id: 0, - amount: min_reward_balance, - } - .into(), + Event::RewardsHarvested { staker, pool_id: 0, amount: min_reward_balance }.into(), ); Ok(()) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 26514c6e7327..e866238ad89f 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -306,8 +306,6 @@ pub mod pallet { }, /// An account harvested some rewards. RewardsHarvested { - /// The caller. - caller: T::AccountId, /// The staker whos rewards were harvested. staker: T::AccountId, /// The pool. @@ -379,13 +377,12 @@ pub mod pallet { impl Hooks> for Pallet { fn integrity_test() { // The AccountId is at least 8 bytes to contain the unique PalletId. - match >::try_into_account( - &T::PalletId::get(), - ) { - // Some(_) => (), - Some(_) => (), - None => panic!("pallet_asset_rewards: PalletId must be at least 8 bytes"), - } + assert!( + >::try_into_account( + &T::PalletId::get(), + ) + .is_some() + ); } } @@ -545,19 +542,10 @@ pub mod pallet { Ok(()) } - /// Harvest unclaimed pool rewards for a staker. - /// - /// Anyone may harvest rewards on behalf of a staker. If an explicit staker is not provided, - /// the caller is assumed to be the staker. + /// Harvest unclaimed pool rewards for the caller. #[pallet::call_index(3)] - pub fn harvest_rewards( - origin: OriginFor, - pool_id: PoolId, - staker: Option, - ) -> DispatchResult { - let caller = ensure_signed(origin)?; - - let staker = staker.unwrap_or(caller.clone()); + pub fn harvest_rewards(origin: OriginFor, pool_id: PoolId) -> DispatchResult { + let staker = ensure_signed(origin)?; // Always start by updating the pool and staker rewards. let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; @@ -579,15 +567,14 @@ pub mod pallet { // Emit event. Self::deposit_event(Event::RewardsHarvested { - caller: caller.clone(), - staker, + staker: staker.clone(), pool_id, amount: staker_info.rewards, }); // Reset staker rewards. staker_info.rewards = 0u32.into(); - PoolStakers::::insert(pool_id, &caller, staker_info); + PoolStakers::::insert(pool_id, &staker, staker_info); Ok(()) } diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 8014703a511f..8ba06362def5 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -76,7 +76,7 @@ fn assert_hypothetically_earned( <::Assets>::balance(reward_asset_id.clone(), &staker); // Harvest the rewards. - assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker), pool_id, None)); + assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker), pool_id)); // Sanity check: staker rewards are reset to 0. assert_eq!(PoolStakers::::get(pool_id, staker).unwrap().rewards, 0); @@ -548,53 +548,7 @@ mod harvest_rewards { System::set_block_number(20); let balance_before: ::Balance = <::Assets>::balance(reward_asset_id.clone(), &staker); - assert_ok!(StakingRewards::harvest_rewards( - RuntimeOrigin::signed(staker), - pool_id, - None - )); - let balance_after = - <::Assets>::balance(reward_asset_id.clone(), &staker); - - // Assert - assert_eq!( - balance_after - balance_before, - 10 * Pools::::get(pool_id).unwrap().reward_rate_per_block - ); - assert_eq!( - *events().last().unwrap(), - Event::::RewardsHarvested { - caller: staker, - staker, - pool_id, - amount: 10 * Pools::::get(pool_id).unwrap().reward_rate_per_block - } - ); - }); - } - - #[test] - fn succeeds_when_harvesting_for_other_staker() { - new_test_ext().execute_with(|| { - let staker = 1; - let harvester = 2; - let pool_id = 0; - let reward_asset_id = NativeOrWithId::::Native; - create_default_pool(); - - // Stake - System::set_block_number(10); - assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker), pool_id, 1000)); - System::set_block_number(20); - - // Harvest - let balance_before: ::Balance = - <::Assets>::balance(reward_asset_id.clone(), &staker); - assert_ok!(StakingRewards::harvest_rewards( - RuntimeOrigin::signed(harvester), - pool_id, - Some(staker) - )); + assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker), pool_id,)); let balance_after = <::Assets>::balance(reward_asset_id.clone(), &staker); @@ -606,7 +560,6 @@ mod harvest_rewards { assert_eq!( *events().last().unwrap(), Event::::RewardsHarvested { - caller: harvester, staker, pool_id, amount: 10 * Pools::::get(pool_id).unwrap().reward_rate_per_block @@ -622,11 +575,7 @@ mod harvest_rewards { create_default_pool(); assert_err!( - StakingRewards::harvest_rewards( - RuntimeOrigin::signed(non_existent_staker), - 0, - None - ), + StakingRewards::harvest_rewards(RuntimeOrigin::signed(non_existent_staker), 0,), Error::::NonExistentStaker ); }); @@ -642,7 +591,6 @@ mod harvest_rewards { StakingRewards::harvest_rewards( RuntimeOrigin::signed(staker), non_existent_pool_id, - None ), Error::::NonExistentPool ); @@ -1385,7 +1333,7 @@ fn integration() { // Get the pre-harvest balance. let balance_before: ::Balance = <::Assets>::balance(reward_asset_id.clone(), &staker2); - assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker2), pool_id, None)); + assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker2), pool_id)); let balance_after = <::Assets>::balance(reward_asset_id.clone(), &staker2); assert_eq!(balance_after - balance_before, 1233u128); @@ -1417,7 +1365,7 @@ fn integration() { Event::Unstaked { caller: staker1, pool_id, amount: 100 }, Event::PoolExpiryBlockModified { pool_id, new_expiry_block: 60 }, Event::PoolRewardRateModified { pool_id, new_reward_rate_per_block: 50 }, - Event::RewardsHarvested { caller: staker2, staker: staker2, pool_id, amount: 1233 } + Event::RewardsHarvested { staker: staker2, pool_id, amount: 1233 } ] ); }); From f0e05eccb0270757fa5491cda382a7856d97622c Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 28 Aug 2024 16:56:03 +0200 Subject: [PATCH 127/159] optional admin --- .../frame/asset-rewards/src/benchmarking.rs | 12 +++--- substrate/frame/asset-rewards/src/lib.rs | 30 ++++++------- substrate/frame/asset-rewards/src/tests.rs | 42 ++++++++++--------- 3 files changed, 46 insertions(+), 38 deletions(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 0f4ca7767464..7147a22005f1 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -92,7 +92,7 @@ where // reward rate per block min_reward_balance, pool_lifetime::(), - None, + Some(caller), )); Ok(caller_origin) @@ -147,13 +147,13 @@ mod benchmarks { Box::new(reward_asset.clone()), min_balance, pool_lifetime::(), - None, + Some(caller.clone()), ); assert_last_event::( Event::PoolCreated { creator: caller.clone(), - admin: caller, + admin: Some(caller), staked_asset_id: staked_asset, reward_asset_id: reward_asset, reward_rate_per_block: min_balance, @@ -255,9 +255,11 @@ mod benchmarks { let new_admin: T::AccountId = whitelisted_caller(); #[extrinsic_call] - _(caller_origin as T::RuntimeOrigin, 0, new_admin.clone()); + _(caller_origin as T::RuntimeOrigin, 0, Some(new_admin.clone())); - assert_last_event::(Event::PoolAdminModified { pool_id: 0, new_admin }.into()); + assert_last_event::( + Event::PoolAdminModified { pool_id: 0, new_admin: Some(new_admin) }.into(), + ); Ok(()) } diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index e866238ad89f..e16f82acd85f 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -147,8 +147,10 @@ pub struct PoolInfo { reward_rate_per_block: Balance, /// The block the pool will cease distributing rewards. expiry_block: BlockNumber, - /// The account that can manage this pool. - admin: AccountId, + /// The account authorized to manage this pool. + /// + /// If set to `None`, the pool cannot be altered after creation. + admin: Option, /// The total amount of tokens staked in this pool. total_tokens_staked: Balance, /// Total rewards accumulated per token, up to the `last_update_block`. @@ -328,7 +330,7 @@ pub mod pallet { /// The block the pool will cease to accumulate rewards. expiry_block: BlockNumberFor, /// The account allowed to modify the pool. - admin: T::AccountId, + admin: Option, }, /// A pool reward rate was modified by the admin. PoolRewardRateModified { @@ -342,7 +344,9 @@ pub mod pallet { /// The modified pool. pool_id: PoolId, /// The new admin. - new_admin: T::AccountId, + /// + /// If `None`, the pool cannot be altered anymore. + new_admin: Option, }, /// A pool expiry block was modified by the admin. PoolExpiryBlockModified { @@ -391,7 +395,7 @@ pub mod pallet { impl Pallet { /// Create a new reward pool. /// - /// If an explicity admin is not specified, it defaults to the caller. + /// If an admin is not specified, the pool cannot be altered after creation. /// /// The initial pool expiry will be calculated by summing `lifetime` with the block /// number at the time of execution. @@ -405,7 +409,7 @@ pub mod pallet { admin: Option, ) -> DispatchResult { // Check the origin. - let creator = T::CreatePoolOrigin::ensure_origin(origin.clone())?; + let creator = T::CreatePoolOrigin::ensure_origin(origin)?; // Ensure the assets exist. ensure!( @@ -430,9 +434,6 @@ pub mod pallet { let cost = T::Consideration::new(&creator, footprint)?; PoolCost::::insert(pool_id, (creator.clone(), cost)); - // Get the admin, defaulting to the origin. - let admin = admin.unwrap_or(creator.clone()); - // Create the pool. let pool = PoolInfoFor:: { staked_asset_id: *staked_asset_id.clone(), @@ -592,7 +593,7 @@ pub mod pallet { .or_else(|_| ensure_signed(origin))?; let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(caller == pool_info.admin, BadOrigin); + ensure!(pool_info.admin.as_ref().map_or(false, |admin| admin == &caller), BadOrigin); // Always start by updating the pool rewards. let rewards_per_token = Self::reward_per_token(&pool_info)?; @@ -616,13 +617,14 @@ pub mod pallet { pub fn set_pool_admin( origin: OriginFor, pool_id: PoolId, - new_admin: T::AccountId, + new_admin: Option, ) -> DispatchResult { let caller = T::CreatePoolOrigin::ensure_origin(origin.clone()) .or_else(|_| ensure_signed(origin))?; let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin == caller, BadOrigin); + ensure!(pool_info.admin.as_ref().map_or(false, |admin| admin == &caller), BadOrigin); + pool_info.admin = new_admin.clone(); Pools::::insert(pool_id, pool_info); @@ -649,7 +651,7 @@ pub mod pallet { ); let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin == caller, BadOrigin); + ensure!(pool_info.admin.as_ref().map_or(false, |admin| admin == &caller), BadOrigin); // Always start by updating the pool rewards. let reward_per_token = Self::reward_per_token(&pool_info)?; @@ -701,7 +703,7 @@ pub mod pallet { .or_else(|_| ensure_signed(origin))?; let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin == caller, BadOrigin); + ensure!(pool_info.admin.as_ref().map_or(false, |admin| admin == &caller), BadOrigin); T::Assets::transfer( pool_info.reward_asset_id, diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 8ba06362def5..0f3145aef848 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -60,7 +60,7 @@ pub fn create_default_pool_permissioned_admin() { Box::new(DEFAULT_REWARD_ASSET_ID.clone()), DEFAULT_REWARD_RATE_PER_BLOCK, DEFAULT_LIFETIME, - None + Some(PermissionedAccountId::get()), )); } @@ -129,7 +129,7 @@ mod create_pool { Box::new(DEFAULT_REWARD_ASSET_ID), DEFAULT_REWARD_RATE_PER_BLOCK, DEFAULT_LIFETIME, - None + Some(PermissionedAccountId::get()) )); // Event is emitted. @@ -142,7 +142,7 @@ mod create_pool { reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: expected_expiry_block, - admin: PermissionedAccountId::get(), + admin: Some(PermissionedAccountId::get()), }] ); @@ -157,7 +157,7 @@ mod create_pool { reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: expected_expiry_block, - admin: PermissionedAccountId::get(), + admin: Some(PermissionedAccountId::get()), total_tokens_staked: 0, reward_per_token_stored: 0, last_update_block: 0 @@ -190,7 +190,7 @@ mod create_pool { staked_asset_id: staked_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, - admin, + admin: Some(admin), expiry_block: expected_expiry_block, }] ); @@ -206,7 +206,7 @@ mod create_pool { staked_asset_id: DEFAULT_STAKED_ASSET_ID, reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, - admin: PermissionedAccountId::get(), + admin: Some(PermissionedAccountId::get()), expiry_block: DEFAULT_LIFETIME + 10, total_tokens_staked: 0, reward_per_token_stored: 0, @@ -219,7 +219,7 @@ mod create_pool { staked_asset_id, reward_asset_id, reward_rate_per_block, - admin, + admin: Some(admin), total_tokens_staked: 0, expiry_block: expected_expiry_block, reward_per_token_stored: 0, @@ -247,7 +247,7 @@ mod create_pool { Box::new(asset.clone()), DEFAULT_REWARD_RATE_PER_BLOCK, DEFAULT_LIFETIME, - None + Some(PermissionedAccountId::get()) )); // Event is emitted. @@ -260,7 +260,7 @@ mod create_pool { reward_asset_id: asset.clone(), reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: expected_expiry_block, - admin: PermissionedAccountId::get(), + admin: Some(PermissionedAccountId::get()), }] ); @@ -275,7 +275,7 @@ mod create_pool { reward_asset_id: asset, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: expected_expiry_block, - admin: PermissionedAccountId::get(), + admin: Some(PermissionedAccountId::get()), total_tokens_staked: 0, reward_per_token_stored: 0, last_update_block: 0 @@ -613,15 +613,15 @@ mod set_pool_admin { assert_ok!(StakingRewards::set_pool_admin( RuntimeOrigin::signed(admin), pool_id, - new_admin + Some(new_admin), )); // Check state assert_eq!( *events().last().unwrap(), - Event::::PoolAdminModified { pool_id, new_admin } + Event::::PoolAdminModified { pool_id, new_admin: Some(new_admin) } ); - assert_eq!(Pools::::get(pool_id).unwrap().admin, new_admin); + assert_eq!(Pools::::get(pool_id).unwrap().admin, Some(new_admin)); }); } @@ -633,14 +633,18 @@ mod set_pool_admin { create_default_pool_permissioned_admin(); // Modify the pool admin - assert_ok!(StakingRewards::set_pool_admin(RuntimeOrigin::root(), pool_id, new_admin)); + assert_ok!(StakingRewards::set_pool_admin( + RuntimeOrigin::root(), + pool_id, + Some(new_admin) + )); // Check state assert_eq!( *events().last().unwrap(), - Event::::PoolAdminModified { pool_id, new_admin } + Event::::PoolAdminModified { pool_id, new_admin: Some(new_admin) } ); - assert_eq!(Pools::::get(pool_id).unwrap().admin, new_admin); + assert_eq!(Pools::::get(pool_id).unwrap().admin, Some(new_admin)); }); } @@ -655,7 +659,7 @@ mod set_pool_admin { StakingRewards::set_pool_admin( RuntimeOrigin::signed(admin), non_existent_pool_id, - new_admin + Some(new_admin) ), Error::::NonExistentPool ); @@ -674,7 +678,7 @@ mod set_pool_admin { StakingRewards::set_pool_admin( RuntimeOrigin::signed(non_admin), pool_id, - new_admin + Some(new_admin) ), BadOrigin ); @@ -1356,7 +1360,7 @@ fn integration() { reward_asset_id, reward_rate_per_block: 100, expiry_block: 25, - admin + admin: Some(admin), }, Event::Staked { caller: staker1, pool_id, amount: 100 }, Event::Staked { caller: staker2, pool_id, amount: 100 }, From 672d3e5cd3e0876ba380226662544ad5b4f6e90f Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 28 Aug 2024 17:13:36 +0200 Subject: [PATCH 128/159] admin tests --- substrate/frame/asset-rewards/src/tests.rs | 118 ++++++++++++++++++++- 1 file changed, 116 insertions(+), 2 deletions(-) diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 0f3145aef848..fff561ea344e 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -17,7 +17,7 @@ use crate::{mock::*, *}; use frame_support::{ - assert_err, assert_ok, hypothetically, + assert_err, assert_noop, assert_ok, hypothetically, traits::{ fungible::NativeOrWithId, fungibles, @@ -52,7 +52,7 @@ pub fn create_default_pool() { )); } -/// The same as [`create_default_pool`], but with the admin parameter set to `None`. +/// The same as [`create_default_pool`], but with the admin parameter set to the creator. pub fn create_default_pool_permissioned_admin() { assert_ok!(StakingRewards::create_pool( RuntimeOrigin::root(), @@ -350,6 +350,44 @@ mod create_pool { ); }); } + + #[test] + fn create_pool_without_admin() { + new_test_ext().execute_with(|| { + assert_eq!(NextPoolId::::get(), 0); + + System::set_block_number(10); + let expected_expiry_block = DEFAULT_LIFETIME + 10; + + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::root(), + Box::new(DEFAULT_STAKED_ASSET_ID), + Box::new(DEFAULT_REWARD_ASSET_ID), + DEFAULT_REWARD_RATE_PER_BLOCK, + DEFAULT_LIFETIME, + None, + )); + + assert_eq!( + events(), + [Event::::PoolCreated { + creator: PermissionedAccountId::get(), + pool_id: 0, + staked_asset_id: DEFAULT_STAKED_ASSET_ID, + reward_asset_id: DEFAULT_REWARD_ASSET_ID, + reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, + expiry_block: expected_expiry_block, + admin: None, + }] + ); + + assert_eq!(Pools::::get(0).unwrap().admin, None); + assert_noop!( + StakingRewards::set_pool_admin(RuntimeOrigin::root(), 0, None,), + BadOrigin + ); + }); + } } mod stake { @@ -684,6 +722,25 @@ mod set_pool_admin { ); }); } + + #[test] + fn clear_admin() { + new_test_ext().execute_with(|| { + let admin = 1; + let pool_id = 0; + create_default_pool(); + + assert_ok!( + StakingRewards::set_pool_admin(RuntimeOrigin::signed(admin), pool_id, None,) + ); + + assert_eq!(Pools::::get(pool_id).unwrap().admin, None); + assert_noop!( + StakingRewards::set_pool_admin(RuntimeOrigin::signed(admin), pool_id, None,), + BadOrigin + ); + }); + } } mod set_pool_expiry_block { @@ -864,6 +921,25 @@ mod set_pool_expiry_block { ); }); } + + #[test] + fn fails_for_pool_without_admin() { + new_test_ext().execute_with(|| { + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::root(), + Box::new(DEFAULT_STAKED_ASSET_ID.clone()), + Box::new(DEFAULT_REWARD_ASSET_ID.clone()), + DEFAULT_REWARD_RATE_PER_BLOCK, + DEFAULT_LIFETIME, + None, + )); + + assert_err!( + StakingRewards::set_pool_expiry_block(RuntimeOrigin::root(), 0, 200), + BadOrigin + ); + }); + } } mod set_pool_reward_rate_per_block { @@ -1001,6 +1077,25 @@ mod set_pool_reward_rate_per_block { ); }); } + + #[test] + fn fails_for_pool_without_admin() { + new_test_ext().execute_with(|| { + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::root(), + Box::new(DEFAULT_STAKED_ASSET_ID.clone()), + Box::new(DEFAULT_REWARD_ASSET_ID.clone()), + DEFAULT_REWARD_RATE_PER_BLOCK, + DEFAULT_LIFETIME, + None, + )); + + assert_err!( + StakingRewards::set_pool_reward_rate_per_block(RuntimeOrigin::root(), 0, 200), + BadOrigin + ); + }); + } } mod deposit_reward_tokens { @@ -1200,6 +1295,25 @@ mod withdraw_reward_tokens { ); }); } + + #[test] + fn fails_for_pool_without_admin() { + new_test_ext().execute_with(|| { + assert_ok!(StakingRewards::create_pool( + RuntimeOrigin::root(), + Box::new(DEFAULT_STAKED_ASSET_ID.clone()), + Box::new(DEFAULT_REWARD_ASSET_ID.clone()), + DEFAULT_REWARD_RATE_PER_BLOCK, + DEFAULT_LIFETIME, + None, + )); + + assert_noop!( + StakingRewards::withdraw_reward_tokens(RuntimeOrigin::root(), 0, 100, 1u128), + BadOrigin + ); + }); + } } /// This integration test From 8f138ddd26456520f3f07df87090fdd598b730a7 Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 28 Aug 2024 17:38:10 +0200 Subject: [PATCH 129/159] store pool account id --- .../frame/asset-rewards/src/benchmarking.rs | 6 ++--- substrate/frame/asset-rewards/src/lib.rs | 23 +++++++++---------- substrate/frame/asset-rewards/src/tests.rs | 20 +++++++++------- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 7147a22005f1..e15b808f01e0 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -210,7 +210,7 @@ mod benchmarks { fn harvest_rewards() -> Result<(), BenchmarkError> { create_reward_pool::()?; - let pool_acc = AssetRewards::::pool_account_id(&0u32).unwrap(); + let pool_acc = AssetRewards::::pool_account_id(&0u32); let min_reward_balance = mint_into::(&pool_acc, &T::BenchmarkHelper::reward_asset()); let staker = whitelisted_caller(); @@ -286,7 +286,7 @@ mod benchmarks { let caller = whitelisted_caller(); let reward_asset = T::BenchmarkHelper::reward_asset(); - let pool_acc = AssetRewards::::pool_account_id(&0u32).unwrap(); + let pool_acc = AssetRewards::::pool_account_id(&0u32); let min_balance = mint_into::(&caller, &reward_asset); let balance_before = T::Assets::balance(reward_asset.clone(), &pool_acc); @@ -315,7 +315,7 @@ mod benchmarks { min_balance, )); - let pool_acc = AssetRewards::::pool_account_id(&0).unwrap(); + let pool_acc = AssetRewards::::pool_account_id(&0); let balance_before = T::Assets::balance(reward_asset.clone(), &pool_acc); #[extrinsic_call] diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index e16f82acd85f..b600463097ed 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -157,6 +157,8 @@ pub struct PoolInfo { reward_per_token_stored: Balance, /// Last block number the pool was updated. last_update_block: BlockNumber, + /// The account that holds the pool's rewards. + account: AccountId, } sp_api::decl_runtime_apis! { @@ -210,7 +212,9 @@ pub mod pallet { /// Overarching event type. type RuntimeEvent: From> + IsType<::RuntimeEvent>; - /// The pallet's id, used for deriving pool account IDs. + /// The pallet's unique identifier, used to derive the pool's account ID. + /// + /// The account ID is derived once during pool creation and stored in the storage. #[pallet::constant] type PalletId: Get; @@ -444,6 +448,7 @@ pub mod pallet { last_update_block: 0u32.into(), expiry_block, admin: admin.clone(), + account: Self::pool_account_id(&pool_id), }; // Insert it into storage. @@ -556,10 +561,9 @@ pub mod pallet { Self::update_pool_and_staker_rewards(&pool_info, &staker_info)?; // Transfer unclaimed rewards from the pool to the staker. - let pool_account_id = Self::pool_account_id(&pool_id)?; T::Assets::transfer( pool_info.reward_asset_id, - &pool_account_id, + &pool_info.account, &staker, staker_info.rewards, // Could kill the account, but only if the pool was already almost empty. @@ -678,11 +682,10 @@ pub mod pallet { ) -> DispatchResult { let caller = ensure_signed(origin)?; let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - let pool_account_id = Self::pool_account_id(&pool_id)?; T::Assets::transfer( pool_info.reward_asset_id, &caller, - &pool_account_id, + &pool_info.account, amount, Preservation::Preserve, )?; @@ -707,7 +710,7 @@ pub mod pallet { T::Assets::transfer( pool_info.reward_asset_id, - &Self::pool_account_id(&pool_id)?, + &pool_info.account, &dest, amount, // Allow completely draining the account. @@ -728,12 +731,8 @@ pub mod pallet { } /// Derive a pool account ID from the pool's ID. - pub fn pool_account_id(id: &PoolId) -> Result { - if Pools::::contains_key(id) { - Ok(T::PalletId::get().into_sub_account_truncating(id)) - } else { - Err(Error::::NonExistentPool.into()) - } + pub fn pool_account_id(id: &PoolId) -> T::AccountId { + T::PalletId::get().into_sub_account_truncating(id) } /// Computes update pool and staker reward state. diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index fff561ea344e..17d581431a68 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -160,7 +160,8 @@ mod create_pool { admin: Some(PermissionedAccountId::get()), total_tokens_staked: 0, reward_per_token_stored: 0, - last_update_block: 0 + last_update_block: 0, + account: StakingRewards::pool_account_id(&0), } )] ); @@ -210,7 +211,8 @@ mod create_pool { expiry_block: DEFAULT_LIFETIME + 10, total_tokens_staked: 0, reward_per_token_stored: 0, - last_update_block: 0 + last_update_block: 0, + account: StakingRewards::pool_account_id(&0), } ), ( @@ -223,7 +225,8 @@ mod create_pool { total_tokens_staked: 0, expiry_block: expected_expiry_block, reward_per_token_stored: 0, - last_update_block: 0 + last_update_block: 0, + account: StakingRewards::pool_account_id(&1), } ) ] @@ -278,7 +281,8 @@ mod create_pool { admin: Some(PermissionedAccountId::get()), total_tokens_staked: 0, reward_per_token_stored: 0, - last_update_block: 0 + last_update_block: 0, + account: StakingRewards::pool_account_id(&0), } )] ); @@ -1109,7 +1113,7 @@ mod deposit_reward_tokens { let amount = 1000; let reward_asset_id = NativeOrWithId::::Native; create_default_pool(); - let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); + let pool_account_id = StakingRewards::pool_account_id(&pool_id); let depositor_balance_before = <::Assets>::balance(reward_asset_id.clone(), &depositor); @@ -1167,7 +1171,7 @@ mod withdraw_reward_tokens { let withdraw_amount = 5; let dest = 10u128; create_default_pool_permissioned_admin(); - let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); + let pool_account_id = StakingRewards::pool_account_id(&pool_id); // Deposit initial reward tokens assert_ok!(StakingRewards::deposit_reward_tokens( @@ -1211,7 +1215,7 @@ mod withdraw_reward_tokens { let withdraw_amount = 5; let dest = 10u128; create_default_pool(); - let pool_account_id = StakingRewards::pool_account_id(&pool_id).unwrap(); + let pool_account_id = StakingRewards::pool_account_id(&pool_id); // Deposit initial reward tokens assert_ok!(StakingRewards::deposit_reward_tokens( @@ -1277,7 +1281,7 @@ mod withdraw_reward_tokens { create_default_pool(); // Deposit initial reward tokens - let pool_account = StakingRewards::pool_account_id(&pool_id).unwrap(); + let pool_account = StakingRewards::pool_account_id(&pool_id); <::Assets>::set_balance( reward_asset_id, &pool_account, From 65c82f9daae3475314447e034e038327a92fec13 Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 28 Aug 2024 17:39:17 +0200 Subject: [PATCH 130/159] fix --- umbrella/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/umbrella/Cargo.toml b/umbrella/Cargo.toml index d89379bfd0aa..7c09deb53b39 100644 --- a/umbrella/Cargo.toml +++ b/umbrella/Cargo.toml @@ -537,7 +537,6 @@ with-tracing = [ "sp-io?/with-tracing", "sp-io?/with-tracing", "sp-tracing?/with-tracing", - "sp-tracing?/with-tracing", ] runtime-full = ["assets-common", "binary-merkle-tree", "bp-header-chain", "bp-messages", "bp-parachains", "bp-polkadot", "bp-polkadot-core", "bp-relayers", "bp-runtime", "bp-test-utils", "bp-xcm-bridge-hub", "bp-xcm-bridge-hub-router", "bridge-hub-common", "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", "cumulus-pallet-parachain-system-proc-macro", "cumulus-pallet-session-benchmarking", "cumulus-pallet-solo-to-para", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-ping", "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-primitives-proof-size-hostfunction", "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-timestamp", "cumulus-primitives-utility", "frame-benchmarking", "frame-benchmarking-pallet-pov", "frame-election-provider-solution-type", "frame-election-provider-support", "frame-executive", "frame-metadata-hash-extension", "frame-support", "frame-support-procedural", "frame-support-procedural-tools-derive", "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", "pallet-alliance", "pallet-asset-conversion", "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", "pallet-asset-tx-payment", "pallet-assets", "pallet-assets-freezer", "pallet-atomic-swap", "pallet-aura", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", "pallet-bags-list", "pallet-balances", "pallet-beefy", "pallet-beefy-mmr", "pallet-bounties", "pallet-bridge-grandpa", "pallet-bridge-messages", "pallet-bridge-parachains", "pallet-bridge-relayers", "pallet-broker", "pallet-child-bounties", "pallet-collator-selection", "pallet-collective", "pallet-collective-content", "pallet-contracts", "pallet-contracts-proc-macro", "pallet-contracts-uapi", "pallet-conviction-voting", "pallet-core-fellowship", "pallet-delegated-staking", "pallet-democracy", "pallet-dev-mode", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", "pallet-fast-unstake", "pallet-glutton", "pallet-grandpa", "pallet-identity", "pallet-im-online", "pallet-indices", "pallet-insecure-randomness-collective-flip", "pallet-lottery", "pallet-membership", "pallet-message-queue", "pallet-migrations", "pallet-mixnet", "pallet-mmr", "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-nis", "pallet-node-authorization", "pallet-nomination-pools", "pallet-nomination-pools-benchmarking", "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", "pallet-paged-list", "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", "pallet-recovery", "pallet-referenda", "pallet-remark", "pallet-revive", "pallet-revive-fixtures", "pallet-revive-proc-macro", "pallet-revive-uapi", "pallet-root-offences", "pallet-root-testing", "pallet-safe-mode", "pallet-salary", "pallet-scheduler", "pallet-scored-pool", "pallet-session", "pallet-session-benchmarking", "pallet-skip-feeless-payment", "pallet-society", "pallet-staking", "pallet-staking-reward-curve", "pallet-staking-reward-fn", "pallet-staking-runtime-api", "pallet-state-trie-migration", "pallet-statement", "pallet-sudo", "pallet-timestamp", "pallet-tips", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", "pallet-tx-pause", "pallet-uniques", "pallet-utility", "pallet-vesting", "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-bridge-hub", "pallet-xcm-bridge-hub-router", "parachains-common", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-metrics", "polkadot-runtime-parachains", "polkadot-sdk-frame", "sc-chain-spec-derive", "sc-tracing-proc-macro", "slot-range-helper", "snowbridge-beacon-primitives", "snowbridge-core", "snowbridge-ethereum", "snowbridge-outbound-queue-merkle-tree", "snowbridge-outbound-queue-runtime-api", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-ethereum-client-fixtures", "snowbridge-pallet-inbound-queue", "snowbridge-pallet-inbound-queue-fixtures", "snowbridge-pallet-outbound-queue", "snowbridge-pallet-system", "snowbridge-router-primitives", "snowbridge-runtime-common", "snowbridge-system-runtime-api", "sp-api", "sp-api-proc-macro", "sp-application-crypto", "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", "sp-consensus-pow", "sp-consensus-slots", "sp-core", "sp-crypto-ec-utils", "sp-crypto-hashing", "sp-crypto-hashing-proc-macro", "sp-debug-derive", "sp-externalities", "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keyring", "sp-keystore", "sp-metadata-ir", "sp-mixnet", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", "sp-runtime", "sp-runtime-interface", "sp-runtime-interface-proc-macro", "sp-session", "sp-staking", "sp-state-machine", "sp-statement-store", "sp-std", "sp-storage", "sp-timestamp", "sp-tracing", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", "sp-version", "sp-version-proc-macro", "sp-wasm-interface", "sp-weights", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", "substrate-bip39", "testnet-parachains-constants", "tracing-gum-proc-macro", "xcm-procedural", "xcm-runtime-apis"] runtime = [ From 6342783b50edfbb592f128fd5daf7ce071ee67c6 Mon Sep 17 00:00:00 2001 From: muharem Date: Wed, 28 Aug 2024 18:11:29 +0200 Subject: [PATCH 131/159] use checked instead saturating --- substrate/frame/asset-rewards/src/lib.rs | 34 ++++++++++++------------ 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index b600463097ed..b804ccd55e0d 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -96,7 +96,7 @@ use frame_support::{ use scale_info::TypeInfo; use sp_core::Get; use sp_runtime::{ - traits::{CheckedAdd, MaybeDisplay, Zero}, + traits::{MaybeDisplay, Zero}, DispatchError, }; use sp_std::boxed::Box; @@ -184,7 +184,10 @@ pub mod pallet { }; use frame_system::pallet_prelude::*; use sp_runtime::{ - traits::{AccountIdConversion, BadOrigin, EnsureDiv, Saturating}, + traits::{ + AccountIdConversion, BadOrigin, EnsureAdd, EnsureAddAssign, EnsureDiv, EnsureMul, + EnsureSub, EnsureSubAssign, Saturating, + }, DispatchResult, }; @@ -375,8 +378,6 @@ pub mod pallet { BlockNumberConversionError, /// The expiry block must be in the future. ExpiryBlockMustBeInTheFuture, - /// An amount overflowed. - Overflow, /// Insufficient funds to create the freeze. InsufficientFunds, } @@ -454,7 +455,7 @@ pub mod pallet { // Insert it into storage. Pools::::insert(pool_id, pool); - NextPoolId::::put(pool_id.checked_add(1).ok_or(Error::::Overflow)?); + NextPoolId::::put(pool_id.ensure_add(1)?); // Emit created event. Self::deposit_event(Event::PoolCreated { @@ -491,13 +492,12 @@ pub mod pallet { )?; // Update Pools. - pool_info.total_tokens_staked = - pool_info.total_tokens_staked.checked_add(&amount).ok_or(Error::::Overflow)?; + pool_info.total_tokens_staked.ensure_add_assign(amount)?; Pools::::insert(pool_id, pool_info); // Update PoolStakers. - staker_info.amount.saturating_accrue(amount); + staker_info.amount.ensure_add_assign(amount)?; PoolStakers::::insert(pool_id, &caller, staker_info); // Emit event. @@ -535,11 +535,11 @@ pub mod pallet { )?; // Update Pools. - pool_info.total_tokens_staked.saturating_reduce(amount); + pool_info.total_tokens_staked.ensure_sub_assign(amount)?; Pools::::insert(pool_id, pool_info); // Update PoolStakers. - staker_info.amount.saturating_reduce(amount); + staker_info.amount.ensure_sub_assign(amount)?; PoolStakers::::insert(pool_id, &caller, staker_info); // Emit event. @@ -785,20 +785,20 @@ pub mod pallet { let rewardable_blocks_elapsed: u32 = match Self::last_block_reward_applicable(pool_info.expiry_block) - .saturating_sub(pool_info.last_update_block) + .ensure_sub(pool_info.last_update_block)? .try_into() { Ok(b) => b, Err(_) => return Err(Error::::BlockNumberConversionError.into()), }; - Ok(pool_info.reward_per_token_stored.saturating_add( + Ok(pool_info.reward_per_token_stored.ensure_add( pool_info .reward_rate_per_block - .saturating_mul(rewardable_blocks_elapsed.into()) - .saturating_mul(PRECISION_SCALING_FACTOR.into()) + .ensure_mul(rewardable_blocks_elapsed.into())? + .ensure_mul(PRECISION_SCALING_FACTOR.into())? .ensure_div(pool_info.total_tokens_staked)?, - )) + )?) } /// Derives the amount of rewards earned by a staker. @@ -810,9 +810,9 @@ pub mod pallet { ) -> Result { Ok(staker_info .amount - .saturating_mul(reward_per_token.saturating_sub(staker_info.reward_per_token_paid)) + .ensure_mul(reward_per_token.ensure_sub(staker_info.reward_per_token_paid)?)? .ensure_div(PRECISION_SCALING_FACTOR.into())? - .saturating_add(staker_info.rewards)) + .ensure_add(staker_info.rewards)?) } fn last_block_reward_applicable(pool_expiry_block: BlockNumberFor) -> BlockNumberFor { From e1d3327bc73972f8fe502a529325d416786ef3a1 Mon Sep 17 00:00:00 2001 From: muharem Date: Thu, 29 Aug 2024 15:45:26 +0200 Subject: [PATCH 132/159] update prdoc --- prdoc/pr_3926.prdoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prdoc/pr_3926.prdoc b/prdoc/pr_3926.prdoc index ec292b5d052c..b8992866c398 100644 --- a/prdoc/pr_3926.prdoc +++ b/prdoc/pr_3926.prdoc @@ -11,7 +11,7 @@ crates: - name: pallet-asset-rewards bump: major - name: polkadot-sdk - bump: major + bump: patch - name: kitchensink-runtime bump: major - name: asset-hub-rococo-runtime @@ -19,8 +19,8 @@ crates: - name: asset-hub-westend-runtime bump: major - name: assets-common - bump: minor + bump: patch - name: rococo-runtime - bump: minor + bump: patch - name: westend-runtime - bump: minor + bump: patch From 0980abac7f4dad09c3dd0d17cb56adc4119e71e5 Mon Sep 17 00:00:00 2001 From: muharem Date: Thu, 29 Aug 2024 15:48:35 +0200 Subject: [PATCH 133/159] fix umbrella --- umbrella/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/umbrella/Cargo.toml b/umbrella/Cargo.toml index 7c09deb53b39..d89379bfd0aa 100644 --- a/umbrella/Cargo.toml +++ b/umbrella/Cargo.toml @@ -537,6 +537,7 @@ with-tracing = [ "sp-io?/with-tracing", "sp-io?/with-tracing", "sp-tracing?/with-tracing", + "sp-tracing?/with-tracing", ] runtime-full = ["assets-common", "binary-merkle-tree", "bp-header-chain", "bp-messages", "bp-parachains", "bp-polkadot", "bp-polkadot-core", "bp-relayers", "bp-runtime", "bp-test-utils", "bp-xcm-bridge-hub", "bp-xcm-bridge-hub-router", "bridge-hub-common", "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", "cumulus-pallet-parachain-system-proc-macro", "cumulus-pallet-session-benchmarking", "cumulus-pallet-solo-to-para", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-ping", "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-primitives-proof-size-hostfunction", "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-timestamp", "cumulus-primitives-utility", "frame-benchmarking", "frame-benchmarking-pallet-pov", "frame-election-provider-solution-type", "frame-election-provider-support", "frame-executive", "frame-metadata-hash-extension", "frame-support", "frame-support-procedural", "frame-support-procedural-tools-derive", "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", "pallet-alliance", "pallet-asset-conversion", "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", "pallet-asset-tx-payment", "pallet-assets", "pallet-assets-freezer", "pallet-atomic-swap", "pallet-aura", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", "pallet-bags-list", "pallet-balances", "pallet-beefy", "pallet-beefy-mmr", "pallet-bounties", "pallet-bridge-grandpa", "pallet-bridge-messages", "pallet-bridge-parachains", "pallet-bridge-relayers", "pallet-broker", "pallet-child-bounties", "pallet-collator-selection", "pallet-collective", "pallet-collective-content", "pallet-contracts", "pallet-contracts-proc-macro", "pallet-contracts-uapi", "pallet-conviction-voting", "pallet-core-fellowship", "pallet-delegated-staking", "pallet-democracy", "pallet-dev-mode", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", "pallet-fast-unstake", "pallet-glutton", "pallet-grandpa", "pallet-identity", "pallet-im-online", "pallet-indices", "pallet-insecure-randomness-collective-flip", "pallet-lottery", "pallet-membership", "pallet-message-queue", "pallet-migrations", "pallet-mixnet", "pallet-mmr", "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-nis", "pallet-node-authorization", "pallet-nomination-pools", "pallet-nomination-pools-benchmarking", "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", "pallet-paged-list", "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", "pallet-recovery", "pallet-referenda", "pallet-remark", "pallet-revive", "pallet-revive-fixtures", "pallet-revive-proc-macro", "pallet-revive-uapi", "pallet-root-offences", "pallet-root-testing", "pallet-safe-mode", "pallet-salary", "pallet-scheduler", "pallet-scored-pool", "pallet-session", "pallet-session-benchmarking", "pallet-skip-feeless-payment", "pallet-society", "pallet-staking", "pallet-staking-reward-curve", "pallet-staking-reward-fn", "pallet-staking-runtime-api", "pallet-state-trie-migration", "pallet-statement", "pallet-sudo", "pallet-timestamp", "pallet-tips", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", "pallet-tx-pause", "pallet-uniques", "pallet-utility", "pallet-vesting", "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-bridge-hub", "pallet-xcm-bridge-hub-router", "parachains-common", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-metrics", "polkadot-runtime-parachains", "polkadot-sdk-frame", "sc-chain-spec-derive", "sc-tracing-proc-macro", "slot-range-helper", "snowbridge-beacon-primitives", "snowbridge-core", "snowbridge-ethereum", "snowbridge-outbound-queue-merkle-tree", "snowbridge-outbound-queue-runtime-api", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-ethereum-client-fixtures", "snowbridge-pallet-inbound-queue", "snowbridge-pallet-inbound-queue-fixtures", "snowbridge-pallet-outbound-queue", "snowbridge-pallet-system", "snowbridge-router-primitives", "snowbridge-runtime-common", "snowbridge-system-runtime-api", "sp-api", "sp-api-proc-macro", "sp-application-crypto", "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", "sp-consensus-pow", "sp-consensus-slots", "sp-core", "sp-crypto-ec-utils", "sp-crypto-hashing", "sp-crypto-hashing-proc-macro", "sp-debug-derive", "sp-externalities", "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keyring", "sp-keystore", "sp-metadata-ir", "sp-mixnet", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", "sp-runtime", "sp-runtime-interface", "sp-runtime-interface-proc-macro", "sp-session", "sp-staking", "sp-state-machine", "sp-statement-store", "sp-std", "sp-storage", "sp-timestamp", "sp-tracing", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", "sp-version", "sp-version-proc-macro", "sp-wasm-interface", "sp-weights", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", "substrate-bip39", "testnet-parachains-constants", "tracing-gum-proc-macro", "xcm-procedural", "xcm-runtime-apis"] runtime = [ From 20e4e49ad9cbda439ac66df1378a3a94a9ed999d Mon Sep 17 00:00:00 2001 From: muharem Date: Thu, 29 Aug 2024 15:57:50 +0200 Subject: [PATCH 134/159] fix umbrella --- umbrella/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/umbrella/Cargo.toml b/umbrella/Cargo.toml index d89379bfd0aa..5d05c753818b 100644 --- a/umbrella/Cargo.toml +++ b/umbrella/Cargo.toml @@ -539,7 +539,7 @@ with-tracing = [ "sp-tracing?/with-tracing", "sp-tracing?/with-tracing", ] -runtime-full = ["assets-common", "binary-merkle-tree", "bp-header-chain", "bp-messages", "bp-parachains", "bp-polkadot", "bp-polkadot-core", "bp-relayers", "bp-runtime", "bp-test-utils", "bp-xcm-bridge-hub", "bp-xcm-bridge-hub-router", "bridge-hub-common", "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", "cumulus-pallet-parachain-system-proc-macro", "cumulus-pallet-session-benchmarking", "cumulus-pallet-solo-to-para", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-ping", "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-primitives-proof-size-hostfunction", "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-timestamp", "cumulus-primitives-utility", "frame-benchmarking", "frame-benchmarking-pallet-pov", "frame-election-provider-solution-type", "frame-election-provider-support", "frame-executive", "frame-metadata-hash-extension", "frame-support", "frame-support-procedural", "frame-support-procedural-tools-derive", "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", "pallet-alliance", "pallet-asset-conversion", "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", "pallet-asset-tx-payment", "pallet-assets", "pallet-assets-freezer", "pallet-atomic-swap", "pallet-aura", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", "pallet-bags-list", "pallet-balances", "pallet-beefy", "pallet-beefy-mmr", "pallet-bounties", "pallet-bridge-grandpa", "pallet-bridge-messages", "pallet-bridge-parachains", "pallet-bridge-relayers", "pallet-broker", "pallet-child-bounties", "pallet-collator-selection", "pallet-collective", "pallet-collective-content", "pallet-contracts", "pallet-contracts-proc-macro", "pallet-contracts-uapi", "pallet-conviction-voting", "pallet-core-fellowship", "pallet-delegated-staking", "pallet-democracy", "pallet-dev-mode", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", "pallet-fast-unstake", "pallet-glutton", "pallet-grandpa", "pallet-identity", "pallet-im-online", "pallet-indices", "pallet-insecure-randomness-collective-flip", "pallet-lottery", "pallet-membership", "pallet-message-queue", "pallet-migrations", "pallet-mixnet", "pallet-mmr", "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-nis", "pallet-node-authorization", "pallet-nomination-pools", "pallet-nomination-pools-benchmarking", "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", "pallet-paged-list", "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", "pallet-recovery", "pallet-referenda", "pallet-remark", "pallet-revive", "pallet-revive-fixtures", "pallet-revive-proc-macro", "pallet-revive-uapi", "pallet-root-offences", "pallet-root-testing", "pallet-safe-mode", "pallet-salary", "pallet-scheduler", "pallet-scored-pool", "pallet-session", "pallet-session-benchmarking", "pallet-skip-feeless-payment", "pallet-society", "pallet-staking", "pallet-staking-reward-curve", "pallet-staking-reward-fn", "pallet-staking-runtime-api", "pallet-state-trie-migration", "pallet-statement", "pallet-sudo", "pallet-timestamp", "pallet-tips", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", "pallet-tx-pause", "pallet-uniques", "pallet-utility", "pallet-vesting", "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-bridge-hub", "pallet-xcm-bridge-hub-router", "parachains-common", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-metrics", "polkadot-runtime-parachains", "polkadot-sdk-frame", "sc-chain-spec-derive", "sc-tracing-proc-macro", "slot-range-helper", "snowbridge-beacon-primitives", "snowbridge-core", "snowbridge-ethereum", "snowbridge-outbound-queue-merkle-tree", "snowbridge-outbound-queue-runtime-api", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-ethereum-client-fixtures", "snowbridge-pallet-inbound-queue", "snowbridge-pallet-inbound-queue-fixtures", "snowbridge-pallet-outbound-queue", "snowbridge-pallet-system", "snowbridge-router-primitives", "snowbridge-runtime-common", "snowbridge-system-runtime-api", "sp-api", "sp-api-proc-macro", "sp-application-crypto", "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", "sp-consensus-pow", "sp-consensus-slots", "sp-core", "sp-crypto-ec-utils", "sp-crypto-hashing", "sp-crypto-hashing-proc-macro", "sp-debug-derive", "sp-externalities", "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keyring", "sp-keystore", "sp-metadata-ir", "sp-mixnet", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", "sp-runtime", "sp-runtime-interface", "sp-runtime-interface-proc-macro", "sp-session", "sp-staking", "sp-state-machine", "sp-statement-store", "sp-std", "sp-storage", "sp-timestamp", "sp-tracing", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", "sp-version", "sp-version-proc-macro", "sp-wasm-interface", "sp-weights", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", "substrate-bip39", "testnet-parachains-constants", "tracing-gum-proc-macro", "xcm-procedural", "xcm-runtime-apis"] +runtime-full = ["assets-common", "binary-merkle-tree", "bp-header-chain", "bp-messages", "bp-parachains", "bp-polkadot", "bp-polkadot-core", "bp-relayers", "bp-runtime", "bp-test-utils", "bp-xcm-bridge-hub", "bp-xcm-bridge-hub-router", "bridge-hub-common", "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", "cumulus-pallet-parachain-system-proc-macro", "cumulus-pallet-session-benchmarking", "cumulus-pallet-solo-to-para", "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-ping", "cumulus-primitives-aura", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "cumulus-primitives-proof-size-hostfunction", "cumulus-primitives-storage-weight-reclaim", "cumulus-primitives-timestamp", "cumulus-primitives-utility", "frame-benchmarking", "frame-benchmarking-pallet-pov", "frame-election-provider-solution-type", "frame-election-provider-support", "frame-executive", "frame-metadata-hash-extension", "frame-support", "frame-support-procedural", "frame-support-procedural-tools-derive", "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", "pallet-alliance", "pallet-asset-conversion", "pallet-asset-conversion-ops", "pallet-asset-conversion-tx-payment", "pallet-asset-rate", "pallet-asset-rewards", "pallet-asset-tx-payment", "pallet-assets", "pallet-assets-freezer", "pallet-atomic-swap", "pallet-aura", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", "pallet-bags-list", "pallet-balances", "pallet-beefy", "pallet-beefy-mmr", "pallet-bounties", "pallet-bridge-grandpa", "pallet-bridge-messages", "pallet-bridge-parachains", "pallet-bridge-relayers", "pallet-broker", "pallet-child-bounties", "pallet-collator-selection", "pallet-collective", "pallet-collective-content", "pallet-contracts", "pallet-contracts-proc-macro", "pallet-contracts-uapi", "pallet-conviction-voting", "pallet-core-fellowship", "pallet-delegated-staking", "pallet-democracy", "pallet-dev-mode", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", "pallet-fast-unstake", "pallet-glutton", "pallet-grandpa", "pallet-identity", "pallet-im-online", "pallet-indices", "pallet-insecure-randomness-collective-flip", "pallet-lottery", "pallet-membership", "pallet-message-queue", "pallet-migrations", "pallet-mixnet", "pallet-mmr", "pallet-multisig", "pallet-nft-fractionalization", "pallet-nfts", "pallet-nfts-runtime-api", "pallet-nis", "pallet-node-authorization", "pallet-nomination-pools", "pallet-nomination-pools-benchmarking", "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", "pallet-paged-list", "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", "pallet-recovery", "pallet-referenda", "pallet-remark", "pallet-revive", "pallet-revive-fixtures", "pallet-revive-proc-macro", "pallet-revive-uapi", "pallet-root-offences", "pallet-root-testing", "pallet-safe-mode", "pallet-salary", "pallet-scheduler", "pallet-scored-pool", "pallet-session", "pallet-session-benchmarking", "pallet-skip-feeless-payment", "pallet-society", "pallet-staking", "pallet-staking-reward-curve", "pallet-staking-reward-fn", "pallet-staking-runtime-api", "pallet-state-trie-migration", "pallet-statement", "pallet-sudo", "pallet-timestamp", "pallet-tips", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", "pallet-tx-pause", "pallet-uniques", "pallet-utility", "pallet-vesting", "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-bridge-hub", "pallet-xcm-bridge-hub-router", "parachains-common", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-metrics", "polkadot-runtime-parachains", "polkadot-sdk-frame", "sc-chain-spec-derive", "sc-tracing-proc-macro", "slot-range-helper", "snowbridge-beacon-primitives", "snowbridge-core", "snowbridge-ethereum", "snowbridge-outbound-queue-merkle-tree", "snowbridge-outbound-queue-runtime-api", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-ethereum-client-fixtures", "snowbridge-pallet-inbound-queue", "snowbridge-pallet-inbound-queue-fixtures", "snowbridge-pallet-outbound-queue", "snowbridge-pallet-system", "snowbridge-router-primitives", "snowbridge-runtime-common", "snowbridge-system-runtime-api", "sp-api", "sp-api-proc-macro", "sp-application-crypto", "sp-arithmetic", "sp-authority-discovery", "sp-block-builder", "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", "sp-consensus-pow", "sp-consensus-slots", "sp-core", "sp-crypto-ec-utils", "sp-crypto-hashing", "sp-crypto-hashing-proc-macro", "sp-debug-derive", "sp-externalities", "sp-genesis-builder", "sp-inherents", "sp-io", "sp-keyring", "sp-keystore", "sp-metadata-ir", "sp-mixnet", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", "sp-runtime", "sp-runtime-interface", "sp-runtime-interface-proc-macro", "sp-session", "sp-staking", "sp-state-machine", "sp-statement-store", "sp-std", "sp-storage", "sp-timestamp", "sp-tracing", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", "sp-version", "sp-version-proc-macro", "sp-wasm-interface", "sp-weights", "staging-parachain-info", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", "substrate-bip39", "testnet-parachains-constants", "tracing-gum-proc-macro", "xcm-procedural", "xcm-runtime-apis"] runtime = [ "frame-benchmarking", "frame-benchmarking-pallet-pov", From 97996e1a3fb9ea8bf33a8fd826f99a02aaba3e4d Mon Sep 17 00:00:00 2001 From: muharem Date: Thu, 29 Aug 2024 16:01:29 +0200 Subject: [PATCH 135/159] remove withdraw_reward_tokens --- .../src/weights/pallet_asset_rewards.rs | 16 -- .../src/weights/pallet_asset_rewards.rs | 16 -- .../frame/asset-rewards/src/benchmarking.rs | 27 --- substrate/frame/asset-rewards/src/lib.rs | 28 --- substrate/frame/asset-rewards/src/tests.rs | 162 ------------------ substrate/frame/asset-rewards/src/weights.rs | 35 ---- 6 files changed, 284 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs index e6eca9176ff5..ec7231a1dc0f 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs @@ -164,20 +164,4 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ForeignAssets::Asset` (r:1 w:1) - /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) - /// Storage: `ForeignAssets::Account` (r:2 w:2) - /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) - fn withdraw_reward_tokens() -> Weight { - // Proof Size summary in bytes: - // Measured: `740` - // Estimated: `7404` - // Minimum execution time: 50_015_000 picoseconds. - Weight::from_parts(51_033_000, 0) - .saturating_add(Weight::from_parts(0, 7404)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(3)) - } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs index 3f9a03b82e25..0dc7e2a6b5f2 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs @@ -164,20 +164,4 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } - /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ForeignAssets::Asset` (r:1 w:1) - /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) - /// Storage: `ForeignAssets::Account` (r:2 w:2) - /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) - fn withdraw_reward_tokens() -> Weight { - // Proof Size summary in bytes: - // Measured: `740` - // Estimated: `7404` - // Minimum execution time: 50_724_000 picoseconds. - Weight::from_parts(51_570_000, 0) - .saturating_add(Weight::from_parts(0, 7404)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(3)) - } } diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index e15b808f01e0..49ab0dcf1e1d 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -301,32 +301,5 @@ mod benchmarks { Ok(()) } - #[benchmark] - fn withdraw_reward_tokens() -> Result<(), BenchmarkError> { - let create_origin = create_reward_pool::()?; - let caller = whitelisted_caller(); - - let reward_asset = T::BenchmarkHelper::reward_asset(); - let min_balance = mint_into::(&caller, &reward_asset); - - assert_ok!(AssetRewards::::deposit_reward_tokens( - RawOrigin::Signed(caller.clone()).into(), - 0, - min_balance, - )); - - let pool_acc = AssetRewards::::pool_account_id(&0); - let balance_before = T::Assets::balance(reward_asset.clone(), &pool_acc); - - #[extrinsic_call] - _(create_origin as T::RuntimeOrigin, 0, min_balance, caller); - - let balance_after = T::Assets::balance(reward_asset.clone(), &pool_acc); - - assert_eq!(balance_before, balance_after + min_balance); - - Ok(()) - } - impl_benchmark_test_suite!(AssetRewards, crate::mock::new_test_ext(), crate::mock::MockRuntime); } diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index b804ccd55e0d..76a288ad59a0 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -691,34 +691,6 @@ pub mod pallet { )?; Ok(()) } - - /// Permissioned method to withdraw reward tokens from a pool. - /// - /// Only the pool admin may perform this operation. - #[pallet::call_index(8)] - pub fn withdraw_reward_tokens( - origin: OriginFor, - pool_id: PoolId, - amount: T::Balance, - dest: T::AccountId, - ) -> DispatchResult { - let caller = T::CreatePoolOrigin::ensure_origin(origin.clone()) - .or_else(|_| ensure_signed(origin))?; - - let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin.as_ref().map_or(false, |admin| admin == &caller), BadOrigin); - - T::Assets::transfer( - pool_info.reward_asset_id, - &pool_info.account, - &dest, - amount, - // Allow completely draining the account. - Preservation::Expendable, - )?; - - Ok(()) - } } impl Pallet { diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 17d581431a68..650295937443 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -1158,168 +1158,6 @@ mod deposit_reward_tokens { } } -mod withdraw_reward_tokens { - use super::*; - - #[test] - fn success_permissioned_admin() { - new_test_ext().execute_with(|| { - let admin = 1; - let pool_id = 0; - let reward_asset_id = NativeOrWithId::::Native; - let initial_deposit = 10; - let withdraw_amount = 5; - let dest = 10u128; - create_default_pool_permissioned_admin(); - let pool_account_id = StakingRewards::pool_account_id(&pool_id); - - // Deposit initial reward tokens - assert_ok!(StakingRewards::deposit_reward_tokens( - RuntimeOrigin::signed(admin), - pool_id, - initial_deposit - )); - - // Withdraw some tokens - let dest_balance_before = - <::Assets>::balance(reward_asset_id.clone(), &dest); - let pool_balance_before = <::Assets>::balance( - reward_asset_id.clone(), - &pool_account_id, - ); - assert_ok!(StakingRewards::withdraw_reward_tokens( - RuntimeOrigin::root(), - pool_id, - withdraw_amount, - dest - )); - let dest_balance_after = - <::Assets>::balance(reward_asset_id.clone(), &dest); - let pool_balance_after = <::Assets>::balance( - reward_asset_id.clone(), - &pool_account_id, - ); - - assert_eq!(pool_balance_after, pool_balance_before - withdraw_amount); - assert_eq!(dest_balance_after, dest_balance_before + withdraw_amount); - }); - } - - #[test] - fn success_signed_origin() { - new_test_ext().execute_with(|| { - let admin = 1; - let pool_id = 0; - let reward_asset_id = NativeOrWithId::::Native; - let initial_deposit = 10; - let withdraw_amount = 5; - let dest = 10u128; - create_default_pool(); - let pool_account_id = StakingRewards::pool_account_id(&pool_id); - - // Deposit initial reward tokens - assert_ok!(StakingRewards::deposit_reward_tokens( - RuntimeOrigin::signed(admin), - pool_id, - initial_deposit - )); - - // Withdraw some tokens - let dest_balance_before = - <::Assets>::balance(reward_asset_id.clone(), &dest); - let pool_balance_before = <::Assets>::balance( - reward_asset_id.clone(), - &pool_account_id, - ); - assert_ok!(StakingRewards::withdraw_reward_tokens( - RuntimeOrigin::signed(admin), - pool_id, - withdraw_amount, - dest - )); - let dest_balance_after = - <::Assets>::balance(reward_asset_id.clone(), &dest); - let pool_balance_after = <::Assets>::balance( - reward_asset_id.clone(), - &pool_account_id, - ); - - assert_eq!(pool_balance_after, pool_balance_before - withdraw_amount); - assert_eq!(dest_balance_after, dest_balance_before + withdraw_amount); - }); - } - - #[test] - fn fails_for_non_existent_pool() { - new_test_ext().execute_with(|| { - assert_err!( - StakingRewards::withdraw_reward_tokens(RuntimeOrigin::signed(1), 900, 100, 1u128), - Error::::NonExistentPool - ); - }); - } - - #[test] - fn fails_for_non_admin() { - new_test_ext().execute_with(|| { - create_default_pool(); - assert_err!( - StakingRewards::withdraw_reward_tokens(RuntimeOrigin::signed(5), 0, 100, 1u128), - BadOrigin - ); - }); - } - - #[test] - fn fails_for_insufficient_pool_balance() { - new_test_ext().execute_with(|| { - let admin = 1; - let pool_id = 0; - let reward_asset_id = NativeOrWithId::::Native; - let initial_deposit = 10000; - let withdraw_amount = 15000; - create_default_pool(); - - // Deposit initial reward tokens - let pool_account = StakingRewards::pool_account_id(&pool_id); - <::Assets>::set_balance( - reward_asset_id, - &pool_account, - initial_deposit, - ); - - assert_err!( - StakingRewards::withdraw_reward_tokens( - RuntimeOrigin::signed(admin), - pool_id, - withdraw_amount, - admin - ), - TokenError::FundsUnavailable - ); - }); - } - - #[test] - fn fails_for_pool_without_admin() { - new_test_ext().execute_with(|| { - assert_ok!(StakingRewards::create_pool( - RuntimeOrigin::root(), - Box::new(DEFAULT_STAKED_ASSET_ID.clone()), - Box::new(DEFAULT_REWARD_ASSET_ID.clone()), - DEFAULT_REWARD_RATE_PER_BLOCK, - DEFAULT_LIFETIME, - None, - )); - - assert_noop!( - StakingRewards::withdraw_reward_tokens(RuntimeOrigin::root(), 0, 100, 1u128), - BadOrigin - ); - }); - } -} - /// This integration test /// 1. Considers 2 stakers each staking and unstaking at different intervals, asserts their /// claimable rewards are adjusted as expected, and that harvesting works. diff --git a/substrate/frame/asset-rewards/src/weights.rs b/substrate/frame/asset-rewards/src/weights.rs index ade36a35797c..ac2c3a6663e8 100644 --- a/substrate/frame/asset-rewards/src/weights.rs +++ b/substrate/frame/asset-rewards/src/weights.rs @@ -55,7 +55,6 @@ pub trait WeightInfo { fn set_pool_admin() -> Weight; fn set_pool_expiry_block() -> Weight; fn deposit_reward_tokens() -> Weight; - fn withdraw_reward_tokens() -> Weight; } /// Weights for `pallet_asset_rewards` using the Substrate node and recommended hardware. @@ -189,23 +188,6 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:2 w:2) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn withdraw_reward_tokens() -> Weight { - // Proof Size summary in bytes: - // Measured: `990` - // Estimated: `6208` - // Minimum execution time: 627_000_000 picoseconds. - Weight::from_parts(718_000_000, 6208) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) - } } // For backwards compatibility and tests. @@ -338,21 +320,4 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:2 w:2) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn withdraw_reward_tokens() -> Weight { - // Proof Size summary in bytes: - // Measured: `990` - // Estimated: `6208` - // Minimum execution time: 627_000_000 picoseconds. - Weight::from_parts(718_000_000, 6208) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) - } } From 4dfa197ed142afdd48212844315399937d426068 Mon Sep 17 00:00:00 2001 From: muharem Date: Thu, 29 Aug 2024 16:38:31 +0200 Subject: [PATCH 136/159] restrict pool altering --- .../frame/asset-rewards/src/benchmarking.rs | 18 +++-- substrate/frame/asset-rewards/src/lib.rs | 9 +++ substrate/frame/asset-rewards/src/tests.rs | 69 +++++++++---------- 3 files changed, 53 insertions(+), 43 deletions(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 49ab0dcf1e1d..c2b47a6a0d40 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -47,7 +47,7 @@ pub trait BenchmarkHelper { } fn pool_lifetime() -> BlockNumberFor { - BlockNumberFor::::max_value() + BlockNumberFor::::from(100u32) } fn create_reward_pool() -> Result @@ -140,6 +140,8 @@ mod benchmarks { assert_ok!(T::Assets::create(reward_asset.clone(), caller.clone(), true, min_balance)); } + let expiry_block = System::::block_number() + pool_lifetime::(); + #[extrinsic_call] _( caller_origin as T::RuntimeOrigin, @@ -157,7 +159,7 @@ mod benchmarks { staked_asset_id: staked_asset, reward_asset_id: reward_asset, reward_rate_per_block: min_balance, - expiry_block: pool_lifetime::(), + expiry_block, pool_id: 0, } .into(), @@ -221,9 +223,7 @@ mod benchmarks { T::Balance::one(), )); - System::::set_block_number( - frame_system::Pallet::::block_number() + BlockNumberFor::::one(), - ); + System::::set_block_number(System::::block_number() + BlockNumberFor::::one()); #[extrinsic_call] _(RawOrigin::Signed(staker.clone()), 0); @@ -239,7 +239,10 @@ mod benchmarks { fn set_pool_reward_rate_per_block() -> Result<(), BenchmarkError> { let caller_origin = create_reward_pool::()?; - let new_reward_rate_per_block = T::Balance::from(5u32); + let new_reward_rate_per_block = + T::Assets::minimum_balance(T::BenchmarkHelper::reward_asset()).max(T::Balance::one()) + + T::Balance::one(); + #[extrinsic_call] _(caller_origin as T::RuntimeOrigin, 0, new_reward_rate_per_block); @@ -268,7 +271,8 @@ mod benchmarks { fn set_pool_expiry_block() -> Result<(), BenchmarkError> { let create_origin = create_reward_pool::()?; - let new_expiry_block = pool_lifetime::() - BlockNumberFor::::one(); + let new_expiry_block = + System::::block_number() + pool_lifetime::() + BlockNumberFor::::one(); #[extrinsic_call] _(create_origin as T::RuntimeOrigin, 0, new_expiry_block); diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 76a288ad59a0..eb54f1157cd0 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -380,6 +380,10 @@ pub mod pallet { ExpiryBlockMustBeInTheFuture, /// Insufficient funds to create the freeze. InsufficientFunds, + /// The expiry block can be only extended. + ExpiryCut, + /// The reward rate per block can be only increased. + RewardRateCut, } #[pallet::hooks] @@ -598,6 +602,10 @@ pub mod pallet { let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; ensure!(pool_info.admin.as_ref().map_or(false, |admin| admin == &caller), BadOrigin); + ensure!( + new_reward_rate_per_block > pool_info.reward_rate_per_block, + Error::::RewardRateCut + ); // Always start by updating the pool rewards. let rewards_per_token = Self::reward_per_token(&pool_info)?; @@ -656,6 +664,7 @@ pub mod pallet { let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; ensure!(pool_info.admin.as_ref().map_or(false, |admin| admin == &caller), BadOrigin); + ensure!(new_expiry_block > pool_info.expiry_block, Error::::ExpiryCut); // Always start by updating the pool rewards. let reward_per_token = Self::reward_per_token(&pool_info)?; diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 650295937443..d84229c1b267 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -754,7 +754,7 @@ mod set_pool_expiry_block { fn success_permissioned_admin() { new_test_ext().execute_with(|| { let pool_id = 0; - let new_expiry_block = 200u64; + let new_expiry_block = System::block_number() + DEFAULT_LIFETIME + 1u64; create_default_pool_permissioned_admin(); assert_ok!(StakingRewards::set_pool_expiry_block( @@ -777,7 +777,7 @@ mod set_pool_expiry_block { new_test_ext().execute_with(|| { let admin = 1; let pool_id = 0; - let new_expiry_block = 200u64; + let new_expiry_block = System::block_number() + DEFAULT_LIFETIME + 1u64; create_default_pool(); assert_ok!(StakingRewards::set_pool_expiry_block( @@ -843,34 +843,15 @@ mod set_pool_expiry_block { } #[test] - fn halts_reward_accumulation() { + fn fails_to_cutback_expiration() { new_test_ext().execute_with(|| { let admin = 1; - let staker = 2; let pool_id = 0; create_default_pool(); - // Earn 10 blocks of rewards - System::set_block_number(10); - assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker), pool_id, 1000)); - System::set_block_number(20); - assert_hypothetically_earned(staker, 100 * 10, pool_id, NativeOrWithId::::Native); - - // Cut off rewards earlier than original expiry - System::set_block_number(21); - assert_ok!(StakingRewards::set_pool_expiry_block( - RuntimeOrigin::signed(admin), - pool_id, - 30 - )); - System::set_block_number(50); - - // Staker has been in pool with rewards active for 20 blocks total - assert_hypothetically_earned( - staker, - 100 * 20 - 1, // -1 rounding error - pool_id, - NativeOrWithId::::Native, + assert_noop!( + StakingRewards::set_pool_expiry_block(RuntimeOrigin::signed(admin), pool_id, 30), + Error::::ExpiryCut ); }); } @@ -1017,7 +998,7 @@ mod set_pool_reward_rate_per_block { let admin = 1; let staker = 2; let pool_id = 0; - let new_reward_rate = 50; + let new_reward_rate = 150; create_default_pool(); // Stake some tokens, and accumulate 10 blocks of rewards at the default pool rate (100) @@ -1025,7 +1006,7 @@ mod set_pool_reward_rate_per_block { assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker), pool_id, 1000)); System::set_block_number(20); - // Halve the reward rate + // Increase the reward rate assert_ok!(StakingRewards::set_pool_reward_rate_per_block( RuntimeOrigin::signed(admin), pool_id, @@ -1100,6 +1081,22 @@ mod set_pool_reward_rate_per_block { ); }); } + + #[test] + fn fails_to_decrease() { + new_test_ext().execute_with(|| { + create_default_pool_permissioned_admin(); + + assert_noop!( + StakingRewards::set_pool_reward_rate_per_block( + RuntimeOrigin::root(), + 0, + DEFAULT_REWARD_RATE_PER_BLOCK - 1 + ), + Error::::RewardRateCut + ); + }); + } } mod deposit_reward_tokens { @@ -1273,7 +1270,7 @@ fn integration() { assert_hypothetically_earned(staker1, 1066, pool_id, reward_asset_id.clone()); assert_hypothetically_earned(staker2, 933, pool_id, reward_asset_id.clone()); - // Block 55: Halve the block reward. + // Block 55: Increase the block reward. // - Staker 1 has earned 1065 tokens. // - Staker 2 has earned 1133 (933 + 2 * 100) tokens. // - Staker 2 is earning 50 tokens per block. @@ -1281,29 +1278,29 @@ fn integration() { assert_ok!(StakingRewards::set_pool_reward_rate_per_block( RuntimeOrigin::signed(admin), pool_id, - 50 + 150 )); assert_hypothetically_earned(staker1, 1066, pool_id, reward_asset_id.clone()); assert_hypothetically_earned(staker2, 1133, pool_id, reward_asset_id.clone()); // Block 57: Staker2 harvests their rewards. System::set_block_number(57); - // - Staker 2 has earned 1233 (1133 + 2 * 50) tokens. - assert_hypothetically_earned(staker2, 1233, pool_id, reward_asset_id.clone()); + // - Staker 2 has earned 1433 (1133 + 2 * 150) tokens. + assert_hypothetically_earned(staker2, 1433, pool_id, reward_asset_id.clone()); // Get the pre-harvest balance. let balance_before: ::Balance = <::Assets>::balance(reward_asset_id.clone(), &staker2); assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker2), pool_id)); let balance_after = <::Assets>::balance(reward_asset_id.clone(), &staker2); - assert_eq!(balance_after - balance_before, 1233u128); + assert_eq!(balance_after - balance_before, 1433u128); // Block 60: Check rewards were adjusted correctly. // - Staker 1 has earned 1065 tokens. - // - Staker 2 has earned 149 (3 * 50) tokens. + // - Staker 2 has earned 450 (3 * 150) tokens. System::set_block_number(60); assert_hypothetically_earned(staker1, 1066, pool_id, reward_asset_id.clone()); - assert_hypothetically_earned(staker2, 150, pool_id, reward_asset_id.clone()); + assert_hypothetically_earned(staker2, 450, pool_id, reward_asset_id.clone()); // Finally, check events. assert_eq!( @@ -1324,8 +1321,8 @@ fn integration() { Event::Unstaked { caller: staker1, pool_id, amount: 100 }, Event::Unstaked { caller: staker1, pool_id, amount: 100 }, Event::PoolExpiryBlockModified { pool_id, new_expiry_block: 60 }, - Event::PoolRewardRateModified { pool_id, new_reward_rate_per_block: 50 }, - Event::RewardsHarvested { staker: staker2, pool_id, amount: 1233 } + Event::PoolRewardRateModified { pool_id, new_reward_rate_per_block: 150 }, + Event::RewardsHarvested { staker: staker2, pool_id, amount: 1433 } ] ); }); From ad922e059b79c8f3f008b0abebc507023c654beb Mon Sep 17 00:00:00 2001 From: muharem Date: Thu, 29 Aug 2024 16:47:42 +0200 Subject: [PATCH 137/159] docs --- substrate/frame/asset-rewards/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index eb54f1157cd0..87b9fbf927f3 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -590,6 +590,8 @@ pub mod pallet { /// Modify a pool reward rate. /// + /// Currently the reward rate can only be increased. + /// /// Only the pool admin may perform this operation. #[pallet::call_index(4)] pub fn set_pool_reward_rate_per_block( @@ -647,6 +649,8 @@ pub mod pallet { /// Set when the pool should expire. /// + /// Currently the expiry block can only be extended. + /// /// Only the pool admin may perform this operation. #[pallet::call_index(6)] pub fn set_pool_expiry_block( From a8240f24907d64bfdbd7c774d2679a2ee80f8c93 Mon Sep 17 00:00:00 2001 From: muharem Date: Thu, 29 Aug 2024 16:51:52 +0200 Subject: [PATCH 138/159] clippy --- substrate/frame/asset-rewards/src/benchmarking.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index c2b47a6a0d40..a962ba812000 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -28,10 +28,7 @@ use frame_support::{ }, }; use frame_system::{pallet_prelude::BlockNumberFor, Pallet as System, RawOrigin}; -use sp_runtime::{ - traits::{Bounded, One}, - Saturating, -}; +use sp_runtime::{traits::One, Saturating}; use sp_std::prelude::*; /// Benchmark Helper From 021bc9cd1fc4cd996ca0df8339d738cefc6a42c4 Mon Sep 17 00:00:00 2001 From: muharem Date: Fri, 30 Aug 2024 13:25:09 +0200 Subject: [PATCH 139/159] use dispatch_time type for expiry parameter --- .../asset-hub-rococo/src/tests/reward_pool.rs | 4 +- .../src/tests/reward_pool.rs | 4 +- .../frame/asset-rewards/src/benchmarking.rs | 16 ++--- substrate/frame/asset-rewards/src/lib.rs | 34 +++++---- substrate/frame/asset-rewards/src/tests.rs | 70 +++++++++++-------- 5 files changed, 74 insertions(+), 54 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reward_pool.rs index 23b8428aded9..66baf13a7aba 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reward_pool.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reward_pool.rs @@ -16,7 +16,7 @@ use crate::imports::*; use codec::Encode; use emulated_integration_tests_common::ASSET_HUB_ROCOCO_ID; -use frame_support::{assert_ok, sp_runtime::traits::Dispatchable}; +use frame_support::{assert_ok, sp_runtime::traits::Dispatchable, traits::schedule::DispatchTime}; use xcm_executor::traits::ConvertLocation; #[test] @@ -74,7 +74,7 @@ fn treasury_creates_asset_reward_pool() { staked_asset_id, reward_asset_id, reward_rate_per_block, - lifetime, + expiry: DispatchTime::After(lifetime), admin } ) diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reward_pool.rs index 88f4ce1fa64a..fbc64137d46a 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reward_pool.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reward_pool.rs @@ -16,7 +16,7 @@ use crate::imports::*; use codec::Encode; use emulated_integration_tests_common::ASSET_HUB_WESTEND_ID; -use frame_support::{assert_ok, sp_runtime::traits::Dispatchable}; +use frame_support::{assert_ok, sp_runtime::traits::Dispatchable, traits::schedule::DispatchTime}; use xcm_executor::traits::ConvertLocation; #[test] @@ -73,7 +73,7 @@ fn treasury_creates_asset_reward_pool() { staked_asset_id, reward_asset_id, reward_rate_per_block, - lifetime, + expiry: DispatchTime::After(lifetime), admin } ) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index a962ba812000..ed2ee4a7a0ae 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -43,8 +43,8 @@ pub trait BenchmarkHelper { fn reward_asset() -> AssetId; } -fn pool_lifetime() -> BlockNumberFor { - BlockNumberFor::::from(100u32) +fn pool_expire() -> DispatchTime> { + DispatchTime::At(BlockNumberFor::::from(100u32)) } fn create_reward_pool() -> Result @@ -88,7 +88,7 @@ where Box::new(reward_asset), // reward rate per block min_reward_balance, - pool_lifetime::(), + pool_expire::(), Some(caller), )); @@ -137,15 +137,13 @@ mod benchmarks { assert_ok!(T::Assets::create(reward_asset.clone(), caller.clone(), true, min_balance)); } - let expiry_block = System::::block_number() + pool_lifetime::(); - #[extrinsic_call] _( caller_origin as T::RuntimeOrigin, Box::new(staked_asset.clone()), Box::new(reward_asset.clone()), min_balance, - pool_lifetime::(), + pool_expire::(), Some(caller.clone()), ); @@ -156,7 +154,7 @@ mod benchmarks { staked_asset_id: staked_asset, reward_asset_id: reward_asset, reward_rate_per_block: min_balance, - expiry_block, + expiry_block: pool_expire::().evaluate(System::::block_number()), pool_id: 0, } .into(), @@ -269,10 +267,10 @@ mod benchmarks { let create_origin = create_reward_pool::()?; let new_expiry_block = - System::::block_number() + pool_lifetime::() + BlockNumberFor::::one(); + pool_expire::().evaluate(System::::block_number()) + BlockNumberFor::::one(); #[extrinsic_call] - _(create_origin as T::RuntimeOrigin, 0, new_expiry_block); + _(create_origin as T::RuntimeOrigin, 0, DispatchTime::At(new_expiry_block)); assert_last_event::( Event::PoolExpiryBlockModified { pool_id: 0, new_expiry_block }.into(), diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 87b9fbf927f3..00e8e792416f 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -89,6 +89,7 @@ use codec::Codec; use frame_support::{ traits::{ fungibles::{Inspect, Mutate}, + schedule::DispatchTime, tokens::Balance, }, PalletId, @@ -186,7 +187,7 @@ pub mod pallet { use sp_runtime::{ traits::{ AccountIdConversion, BadOrigin, EnsureAdd, EnsureAddAssign, EnsureDiv, EnsureMul, - EnsureSub, EnsureSubAssign, Saturating, + EnsureSub, EnsureSubAssign, }, DispatchResult, }; @@ -404,17 +405,22 @@ pub mod pallet { impl Pallet { /// Create a new reward pool. /// - /// If an admin is not specified, the pool cannot be altered after creation. - /// - /// The initial pool expiry will be calculated by summing `lifetime` with the block - /// number at the time of execution. + /// Parameters: + /// - `origin`: must be `Config::CreatePoolOrigin`; + /// - `staked_asset_id`: the asset to be staked in the pool; + /// - `reward_asset_id`: the asset to be distributed as rewards; + /// - `reward_rate_per_block`: the amount of reward tokens distributed per block; + /// - `expiry`: the block number at which the pool will cease to accumulate rewards. The + /// [`DispatchTime::After`] variant evaluated at the execution time. + /// - `admin`: the account allowed to modify the pool. If `None`, the pool cannot be + /// altered. #[pallet::call_index(0)] pub fn create_pool( origin: OriginFor, staked_asset_id: Box, reward_asset_id: Box, reward_rate_per_block: T::Balance, - lifetime: BlockNumberFor, + expiry: DispatchTime>, admin: Option, ) -> DispatchResult { // Check the origin. @@ -431,7 +437,7 @@ pub mod pallet { ); // Check the expiry block. - let expiry_block = frame_system::Pallet::::block_number().saturating_add(lifetime); + let expiry_block = expiry.evaluate(frame_system::Pallet::::block_number()); ensure!( expiry_block > frame_system::Pallet::::block_number(), Error::::ExpiryBlockMustBeInTheFuture @@ -656,28 +662,32 @@ pub mod pallet { pub fn set_pool_expiry_block( origin: OriginFor, pool_id: PoolId, - new_expiry_block: BlockNumberFor, + new_expiry: DispatchTime>, ) -> DispatchResult { let caller = T::CreatePoolOrigin::ensure_origin(origin.clone()) .or_else(|_| ensure_signed(origin))?; + let new_expiry = new_expiry.evaluate(frame_system::Pallet::::block_number()); ensure!( - new_expiry_block > frame_system::Pallet::::block_number(), + new_expiry > frame_system::Pallet::::block_number(), Error::::ExpiryBlockMustBeInTheFuture ); let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; ensure!(pool_info.admin.as_ref().map_or(false, |admin| admin == &caller), BadOrigin); - ensure!(new_expiry_block > pool_info.expiry_block, Error::::ExpiryCut); + ensure!(new_expiry > pool_info.expiry_block, Error::::ExpiryCut); // Always start by updating the pool rewards. let reward_per_token = Self::reward_per_token(&pool_info)?; let mut pool_info = Self::update_pool_rewards(&pool_info, reward_per_token)?; - pool_info.expiry_block = new_expiry_block; + pool_info.expiry_block = new_expiry; Pools::::insert(pool_id, pool_info); - Self::deposit_event(Event::PoolExpiryBlockModified { pool_id, new_expiry_block }); + Self::deposit_event(Event::PoolExpiryBlockModified { + pool_id, + new_expiry_block: new_expiry, + }); Ok(()) } diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index d84229c1b267..52ebc3f669ca 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -29,7 +29,7 @@ use sp_runtime::{traits::BadOrigin, ArithmeticError, TokenError}; const DEFAULT_STAKED_ASSET_ID: NativeOrWithId = NativeOrWithId::::WithId(1); const DEFAULT_REWARD_ASSET_ID: NativeOrWithId = NativeOrWithId::::Native; const DEFAULT_REWARD_RATE_PER_BLOCK: u128 = 100; -const DEFAULT_LIFETIME: u64 = 200; +const DEFAULT_EXPIRE_AFTER: u64 = 200; const DEFAULT_ADMIN: u128 = 1; /// Creates a basic pool with values: @@ -47,7 +47,7 @@ pub fn create_default_pool() { Box::new(DEFAULT_STAKED_ASSET_ID.clone()), Box::new(DEFAULT_REWARD_ASSET_ID.clone()), DEFAULT_REWARD_RATE_PER_BLOCK, - DEFAULT_LIFETIME, + DispatchTime::After(DEFAULT_EXPIRE_AFTER), Some(DEFAULT_ADMIN) )); } @@ -59,7 +59,7 @@ pub fn create_default_pool_permissioned_admin() { Box::new(DEFAULT_STAKED_ASSET_ID.clone()), Box::new(DEFAULT_REWARD_ASSET_ID.clone()), DEFAULT_REWARD_RATE_PER_BLOCK, - DEFAULT_LIFETIME, + DispatchTime::After(DEFAULT_EXPIRE_AFTER), Some(PermissionedAccountId::get()), )); } @@ -119,7 +119,7 @@ mod create_pool { assert_eq!(NextPoolId::::get(), 0); System::set_block_number(10); - let expected_expiry_block = DEFAULT_LIFETIME + 10; + let expected_expiry_block = DEFAULT_EXPIRE_AFTER + 10; // Create a pool with default values, and no admin override so [`PermissionedAccountId`] // is admin. @@ -128,7 +128,7 @@ mod create_pool { Box::new(DEFAULT_STAKED_ASSET_ID), Box::new(DEFAULT_REWARD_ASSET_ID), DEFAULT_REWARD_RATE_PER_BLOCK, - DEFAULT_LIFETIME, + DispatchTime::After(DEFAULT_EXPIRE_AFTER), Some(PermissionedAccountId::get()) )); @@ -178,7 +178,7 @@ mod create_pool { Box::new(staked_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, - expiry_block, + DispatchTime::After(expiry_block), Some(admin) )); @@ -208,7 +208,7 @@ mod create_pool { reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, admin: Some(PermissionedAccountId::get()), - expiry_block: DEFAULT_LIFETIME + 10, + expiry_block: DEFAULT_EXPIRE_AFTER + 10, total_tokens_staked: 0, reward_per_token_stored: 0, last_update_block: 0, @@ -240,7 +240,7 @@ mod create_pool { assert_eq!(NextPoolId::::get(), 0); System::set_block_number(10); - let expected_expiry_block = DEFAULT_LIFETIME + 10; + let expected_expiry_block = DEFAULT_EXPIRE_AFTER + 10; // Create a pool with the same staking and reward asset. let asset = NativeOrWithId::::Native; @@ -249,7 +249,7 @@ mod create_pool { Box::new(asset.clone()), Box::new(asset.clone()), DEFAULT_REWARD_RATE_PER_BLOCK, - DEFAULT_LIFETIME, + DispatchTime::After(DEFAULT_EXPIRE_AFTER), Some(PermissionedAccountId::get()) )); @@ -301,7 +301,7 @@ mod create_pool { Box::new(valid_asset.clone()), Box::new(invalid_asset.clone()), 10, - 10u64, + DispatchTime::After(10u64), None ), Error::::NonExistentAsset @@ -313,7 +313,7 @@ mod create_pool { Box::new(invalid_asset.clone()), Box::new(valid_asset.clone()), 10, - 10u64, + DispatchTime::After(10u64), None ), Error::::NonExistentAsset @@ -325,7 +325,7 @@ mod create_pool { Box::new(invalid_asset.clone()), Box::new(invalid_asset.clone()), 10, - 10u64, + DispatchTime::After(10u64), None ), Error::::NonExistentAsset @@ -347,7 +347,7 @@ mod create_pool { Box::new(staked_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, - expiry_block, + DispatchTime::After(expiry_block), None ), BadOrigin @@ -361,14 +361,14 @@ mod create_pool { assert_eq!(NextPoolId::::get(), 0); System::set_block_number(10); - let expected_expiry_block = DEFAULT_LIFETIME + 10; + let expected_expiry_block = DEFAULT_EXPIRE_AFTER + 10; assert_ok!(StakingRewards::create_pool( RuntimeOrigin::root(), Box::new(DEFAULT_STAKED_ASSET_ID), Box::new(DEFAULT_REWARD_ASSET_ID), DEFAULT_REWARD_RATE_PER_BLOCK, - DEFAULT_LIFETIME, + DispatchTime::After(DEFAULT_EXPIRE_AFTER), None, )); @@ -754,13 +754,13 @@ mod set_pool_expiry_block { fn success_permissioned_admin() { new_test_ext().execute_with(|| { let pool_id = 0; - let new_expiry_block = System::block_number() + DEFAULT_LIFETIME + 1u64; + let new_expiry_block = System::block_number() + DEFAULT_EXPIRE_AFTER + 1u64; create_default_pool_permissioned_admin(); assert_ok!(StakingRewards::set_pool_expiry_block( RuntimeOrigin::root(), pool_id, - new_expiry_block + DispatchTime::At(new_expiry_block), )); // Check state @@ -777,13 +777,13 @@ mod set_pool_expiry_block { new_test_ext().execute_with(|| { let admin = 1; let pool_id = 0; - let new_expiry_block = System::block_number() + DEFAULT_LIFETIME + 1u64; + let new_expiry_block = System::block_number() + DEFAULT_EXPIRE_AFTER + 1u64; create_default_pool(); assert_ok!(StakingRewards::set_pool_expiry_block( RuntimeOrigin::signed(admin), pool_id, - new_expiry_block + DispatchTime::At(new_expiry_block) )); // Check state @@ -828,7 +828,7 @@ mod set_pool_expiry_block { assert_ok!(StakingRewards::set_pool_expiry_block( RuntimeOrigin::signed(admin), pool_id, - new_expiry_block + DispatchTime::At(new_expiry_block) )); System::set_block_number(350); @@ -850,7 +850,11 @@ mod set_pool_expiry_block { create_default_pool(); assert_noop!( - StakingRewards::set_pool_expiry_block(RuntimeOrigin::signed(admin), pool_id, 30), + StakingRewards::set_pool_expiry_block( + RuntimeOrigin::signed(admin), + pool_id, + DispatchTime::After(30) + ), Error::::ExpiryCut ); }); @@ -867,7 +871,7 @@ mod set_pool_expiry_block { StakingRewards::set_pool_expiry_block( RuntimeOrigin::signed(admin), non_existent_pool_id, - new_expiry_block + DispatchTime::After(new_expiry_block) ), Error::::NonExistentPool ); @@ -886,7 +890,7 @@ mod set_pool_expiry_block { StakingRewards::set_pool_expiry_block( RuntimeOrigin::signed(non_admin), pool_id, - new_expiry_block + DispatchTime::After(new_expiry_block) ), BadOrigin ); @@ -901,7 +905,11 @@ mod set_pool_expiry_block { create_default_pool(); System::set_block_number(50); assert_err!( - StakingRewards::set_pool_expiry_block(RuntimeOrigin::signed(admin), pool_id, 40u64), + StakingRewards::set_pool_expiry_block( + RuntimeOrigin::signed(admin), + pool_id, + DispatchTime::At(40u64) + ), Error::::ExpiryBlockMustBeInTheFuture ); }); @@ -915,12 +923,16 @@ mod set_pool_expiry_block { Box::new(DEFAULT_STAKED_ASSET_ID.clone()), Box::new(DEFAULT_REWARD_ASSET_ID.clone()), DEFAULT_REWARD_RATE_PER_BLOCK, - DEFAULT_LIFETIME, + DispatchTime::After(DEFAULT_EXPIRE_AFTER), None, )); assert_err!( - StakingRewards::set_pool_expiry_block(RuntimeOrigin::root(), 0, 200), + StakingRewards::set_pool_expiry_block( + RuntimeOrigin::root(), + 0, + DispatchTime::After(200) + ), BadOrigin ); }); @@ -1071,7 +1083,7 @@ mod set_pool_reward_rate_per_block { Box::new(DEFAULT_STAKED_ASSET_ID.clone()), Box::new(DEFAULT_REWARD_ASSET_ID.clone()), DEFAULT_REWARD_RATE_PER_BLOCK, - DEFAULT_LIFETIME, + DispatchTime::After(DEFAULT_EXPIRE_AFTER), None, )); @@ -1180,7 +1192,7 @@ fn integration() { Box::new(staked_asset_id.clone()), Box::new(reward_asset_id.clone()), reward_rate_per_block, - lifetime, + DispatchTime::After(lifetime), Some(admin) )); let pool_id = 0; @@ -1257,7 +1269,7 @@ fn integration() { assert_ok!(StakingRewards::set_pool_expiry_block( RuntimeOrigin::signed(admin), pool_id, - 60u64 + DispatchTime::At(60u64), )); assert_hypothetically_earned(staker1, 1066, pool_id, reward_asset_id.clone()); assert_hypothetically_earned(staker2, 733, pool_id, reward_asset_id.clone()); From 3a82f5e3f18bff80c3a5fae357a52c8ed7a71099 Mon Sep 17 00:00:00 2001 From: Muharem Date: Thu, 12 Sep 2024 16:23:19 +0200 Subject: [PATCH 140/159] Apply suggestions from code review Co-authored-by: Guillaume Thiolliere --- substrate/frame/asset-rewards/src/lib.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 00e8e792416f..fc4a487757fb 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -56,7 +56,7 @@ //! //! ## Implementation Notes //! -//! Internal logic functions such as `update_pool_and_staker_rewards` where deliberately written +//! Internal logic functions such as `update_pool_and_staker_rewards` were deliberately written //! without side-effects. //! //! Storage interaction such as reads and writes are instead all performed in the top level @@ -81,11 +81,10 @@ #![deny(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -use codec::{Decode, Encode, MaxEncodedLen}; -use frame_system::pallet_prelude::BlockNumberFor; pub use pallet::*; -use codec::Codec; +use codec::{Codec, Decode, Encode, MaxEncodedLen}; +use frame_system::pallet_prelude::BlockNumberFor; use frame_support::{ traits::{ fungibles::{Inspect, Mutate}, @@ -241,14 +240,11 @@ pub mod pallet { /// Freezer for the Assets. type AssetsFreezer: MutateFreeze< Self::AccountId, - Id = Self::RuntimeFreezeReason, + Id: From, AssetId = Self::AssetId, Balance = Self::Balance, >; - /// The overarching freeze reason. - type RuntimeFreezeReason: From; - /// Means for associating a cost with the on-chain storage of pool information, which /// is incurred by the pool creator. /// From 8cccdb82c6edf5285b9580ab0a56c3363f893f94 Mon Sep 17 00:00:00 2001 From: muharem Date: Thu, 12 Sep 2024 16:32:15 +0200 Subject: [PATCH 141/159] RuntimeFreezeReason config parameter --- substrate/frame/asset-rewards/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index fc4a487757fb..47538a773fce 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -84,7 +84,6 @@ pub use pallet::*; use codec::{Codec, Decode, Encode, MaxEncodedLen}; -use frame_system::pallet_prelude::BlockNumberFor; use frame_support::{ traits::{ fungibles::{Inspect, Mutate}, @@ -93,6 +92,7 @@ use frame_support::{ }, PalletId, }; +use frame_system::pallet_prelude::BlockNumberFor; use scale_info::TypeInfo; use sp_core::Get; use sp_runtime::{ @@ -240,11 +240,14 @@ pub mod pallet { /// Freezer for the Assets. type AssetsFreezer: MutateFreeze< Self::AccountId, - Id: From, + Id = Self::RuntimeFreezeReason, AssetId = Self::AssetId, Balance = Self::Balance, >; + /// The overarching freeze reason. + type RuntimeFreezeReason: From; + /// Means for associating a cost with the on-chain storage of pool information, which /// is incurred by the pool creator. /// From ecfc903c47e3ac14d5337a86613a46b5092b2b10 Mon Sep 17 00:00:00 2001 From: muharem Date: Thu, 12 Sep 2024 16:38:48 +0200 Subject: [PATCH 142/159] review fixes --- .../assets/asset-hub-rococo/src/lib.rs | 15 ++++++++---- .../assets/asset-hub-westend/src/lib.rs | 15 ++++++++---- polkadot/runtime/rococo/src/xcm_config.rs | 5 +++- substrate/bin/node/runtime/src/lib.rs | 18 ++++++++++---- substrate/frame/asset-rewards/Cargo.toml | 24 +++++++++---------- .../frame/asset-rewards/src/benchmarking.rs | 23 ++++++++++++++++++ substrate/frame/asset-rewards/src/lib.rs | 14 +++++------ substrate/frame/support/src/traits.rs | 5 ++-- substrate/frame/support/src/traits/storage.rs | 12 ++++++++++ 9 files changed, 96 insertions(+), 35 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index afac425bd89e..988baf68b85f 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -63,8 +63,8 @@ use frame_support::{ fungible::{self, HoldConsideration}, fungibles, tokens::imbalance::ResolveAssetTo, - AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, EitherOfDiverse, - Equals, InstanceFilter, LinearStoragePrice, TransformOrigin, + AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, + ConstantStoragePrice, EitherOfDiverse, Equals, InstanceFilter, TransformOrigin, }, weights::{ConstantMultiplier, Weight, WeightToFee as _}, BoundedVec, PalletId, @@ -1023,9 +1023,10 @@ impl pallet_asset_rewards::benchmarking::BenchmarkHelper parameter_types! { pub const AssetRewardsPalletId: PalletId = PalletId(*b"py/astrd"); - pub const PoolCreationDeposit: Balance = deposit(1, 95); pub const RewardsPoolCreationHoldReason: RuntimeHoldReason = RuntimeHoldReason::AssetRewards(pallet_asset_rewards::HoldReason::PoolCreation); + // 1 item, 135 bytes into the storage on pool creation. + pub const StakePoolCreationDeposit: Balance = deposit(1, 135); } impl pallet_asset_rewards::Config for Runtime { @@ -1041,7 +1042,7 @@ impl pallet_asset_rewards::Config for Runtime { AccountId, Balances, RewardsPoolCreationHoldReason, - LinearStoragePrice, Balance>, + ConstantStoragePrice, >; type WeightInfo = weights::pallet_asset_rewards::WeightInfo; #[cfg(feature = "runtime-benchmarks")] @@ -1503,6 +1504,12 @@ impl_runtime_apis! { } } + impl pallet_asset_rewards::AssetRewards for Runtime { + fn pool_creation_cost() -> Balance { + StakePoolCreationDeposit::get() + } + } + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { 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 2986a7e3e6cb..1bf82d43ed84 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -47,8 +47,8 @@ use frame_support::{ fungible::HoldConsideration, fungibles, tokens::{imbalance::ResolveAssetTo, nonfungibles_v2::Inspect}, - AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Equals, - InstanceFilter, LinearStoragePrice, TransformOrigin, + AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, + ConstantStoragePrice, Equals, InstanceFilter, TransformOrigin, }, weights::{ConstantMultiplier, Weight, WeightToFee as _}, BoundedVec, PalletId, @@ -459,9 +459,10 @@ impl pallet_asset_rewards::benchmarking::BenchmarkHelper parameter_types! { pub const AssetRewardsPalletId: PalletId = PalletId(*b"py/astrd"); - pub const PoolCreationDeposit: Balance = deposit(1, 95); pub const RewardsPoolCreationHoldReason: RuntimeHoldReason = RuntimeHoldReason::AssetRewards(pallet_asset_rewards::HoldReason::PoolCreation); + // 1 item, 135 bytes into the storage on pool creation. + pub const StakePoolCreationDeposit: Balance = deposit(1, 135); } impl pallet_asset_rewards::Config for Runtime { @@ -477,7 +478,7 @@ impl pallet_asset_rewards::Config for Runtime { AccountId, Balances, RewardsPoolCreationHoldReason, - LinearStoragePrice, Balance>, + ConstantStoragePrice, >; type WeightInfo = weights::pallet_asset_rewards::WeightInfo; #[cfg(feature = "runtime-benchmarks")] @@ -1598,6 +1599,12 @@ impl_runtime_apis! { } } + impl pallet_asset_rewards::AssetRewards for Runtime { + fn pool_creation_cost() -> Balance { + StakePoolCreationDeposit::get() + } + } + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { diff --git a/polkadot/runtime/rococo/src/xcm_config.rs b/polkadot/runtime/rococo/src/xcm_config.rs index fccb967eede3..7bac7a97279f 100644 --- a/polkadot/runtime/rococo/src/xcm_config.rs +++ b/polkadot/runtime/rococo/src/xcm_config.rs @@ -271,7 +271,10 @@ impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; // Note that this configuration of `SendXcmOrigin` is different from the one present in // production. - type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin< + RuntimeOrigin, + (LocalPalletOriginToLocation, LocalOriginToLocation), + >; type XcmRouter = XcmRouter; // Anyone can execute XCM messages locally. type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index de3bf731589e..88542f4086cd 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -49,10 +49,10 @@ use frame_support::{ imbalance::ResolveAssetTo, nonfungibles_v2::Inspect, pay::PayAssetFromAccount, GetSalary, PayFromAccount, }, - AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU16, ConstU32, Contains, Currency, - EitherOfDiverse, EnsureOriginWithArg, EqualPrivilegeOnly, Imbalance, InsideBoth, - InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, LockIdentifier, Nothing, - OnUnbalanced, VariantCountOf, WithdrawReasons, + AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU16, ConstU32, ConstantStoragePrice, + Contains, Currency, EitherOfDiverse, EnsureOriginWithArg, EqualPrivilegeOnly, Imbalance, + InsideBoth, InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, LockIdentifier, + Nothing, OnUnbalanced, VariantCountOf, WithdrawReasons, }, weights::{ constants::{ @@ -1796,6 +1796,8 @@ parameter_types! { pub const StakingRewardsPalletId: PalletId = PalletId(*b"py/stkrd"); pub const CreationHoldReason: RuntimeHoldReason = RuntimeHoldReason::AssetRewards(pallet_asset_rewards::HoldReason::PoolCreation); + // 1 item, 135 bytes into the storage on pool creation. + pub const StakePoolCreationDeposit: Balance = deposit(1, 135); } impl pallet_asset_rewards::Config for Runtime { @@ -1812,7 +1814,7 @@ impl pallet_asset_rewards::Config for Runtime { AccountId, Balances, CreationHoldReason, - LinearStoragePrice, Balance>, + ConstantStoragePrice, >; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = AssetRewardsBenchmarkHelper; @@ -3366,6 +3368,12 @@ impl_runtime_apis! { } } + impl pallet_asset_rewards::AssetRewards for Runtime { + fn pool_creation_cost() -> Balance { + StakePoolCreationDeposit::get() + } + } + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { diff --git a/substrate/frame/asset-rewards/Cargo.toml b/substrate/frame/asset-rewards/Cargo.toml index da73ab126021..c8fe8f13f923 100644 --- a/substrate/frame/asset-rewards/Cargo.toml +++ b/substrate/frame/asset-rewards/Cargo.toml @@ -15,23 +15,23 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { workspace = true, default-features = false } -frame-support = { workspace = true, default-features = false, features = ["experimental"] } -frame-system = { workspace = true, default-features = false } -frame-benchmarking = { workspace = true, default-features = false, optional = true } -scale-info = { workspace = true, default-features = false, features = ["derive"] } -sp-api = { workspace = true, default-features = false } -sp-core = { workspace = true, default-features = false } -sp-io = { workspace = true, default-features = false } -sp-std = { workspace = true, default-features = false } -sp-runtime = { workspace = true, default-features = false } -sp-arithmetic = { workspace = true, default-features = false } +codec = { workspace = true } +frame-support = { workspace = true, features = ["experimental"] } +frame-system = { workspace = true } +frame-benchmarking = { workspace = true, optional = true } +scale-info = { workspace = true, features = ["derive"] } +sp-api = { workspace = true } +sp-core = { workspace = true } +sp-io = { workspace = true } +sp-std = { workspace = true } +sp-runtime = { workspace = true } +sp-arithmetic = { workspace = true } [dev-dependencies] pallet-balances = { workspace = true } pallet-assets = { workspace = true } pallet-assets-freezer = { workspace = true } -primitive-types = { workspace = true, default-features = false, features = ["codec", "num-traits", "scale-info"] } +primitive-types = { workspace = true, features = ["codec", "num-traits", "scale-info"] } [features] default = ["std"] diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index ed2ee4a7a0ae..bab8ebbec411 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -170,6 +170,13 @@ mod benchmarks { let staker: T::AccountId = whitelisted_caller(); let min_balance = mint_into::(&staker, &T::BenchmarkHelper::staked_asset()); + // stake first to get worth case benchmark. + assert_ok!(AssetRewards::::stake( + RawOrigin::Signed(staker.clone()).into(), + 0, + min_balance + )); + #[extrinsic_call] _(RawOrigin::Signed(staker.clone()), 0, min_balance); @@ -234,6 +241,14 @@ mod benchmarks { fn set_pool_reward_rate_per_block() -> Result<(), BenchmarkError> { let caller_origin = create_reward_pool::()?; + // stake first to get worth case benchmark. + { + let staker: T::AccountId = whitelisted_caller(); + let min_balance = mint_into::(&staker, &T::BenchmarkHelper::staked_asset()); + + assert_ok!(AssetRewards::::stake(RawOrigin::Signed(staker).into(), 0, min_balance)); + } + let new_reward_rate_per_block = T::Assets::minimum_balance(T::BenchmarkHelper::reward_asset()).max(T::Balance::one()) + T::Balance::one(); @@ -266,6 +281,14 @@ mod benchmarks { fn set_pool_expiry_block() -> Result<(), BenchmarkError> { let create_origin = create_reward_pool::()?; + // stake first to get worth case benchmark. + { + let staker: T::AccountId = whitelisted_caller(); + let min_balance = mint_into::(&staker, &T::BenchmarkHelper::staked_asset()); + + assert_ok!(AssetRewards::::stake(RawOrigin::Signed(staker).into(), 0, min_balance)); + } + let new_expiry_block = pool_expire::().evaluate(System::::block_number()) + BlockNumberFor::::one(); diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 47538a773fce..03da7ae61fe8 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -389,10 +389,11 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { fn integrity_test() { - // The AccountId is at least 8 bytes to contain the unique PalletId. + // The AccountId is at least 16 bytes to contain the unique PalletId. + let pool_id: PoolId = 1; assert!( - >::try_into_account( - &T::PalletId::get(), + >::try_into_sub_account( + &T::PalletId::get(), pool_id, ) .is_some() ); @@ -770,8 +771,6 @@ pub mod pallet { } /// Derives the current reward per token for this pool. - /// - /// This is a helper function for `update_pool_rewards` and should not be called directly. fn reward_per_token(pool_info: &PoolInfoFor) -> Result { if pool_info.total_tokens_staked.is_zero() { return Ok(pool_info.reward_per_token_stored) @@ -810,8 +809,9 @@ pub mod pallet { } fn last_block_reward_applicable(pool_expiry_block: BlockNumberFor) -> BlockNumberFor { - if frame_system::Pallet::::block_number() < pool_expiry_block { - frame_system::Pallet::::block_number() + let now = frame_system::Pallet::::block_number(); + if now < pool_expiry_block { + now } else { pool_expiry_block } diff --git a/substrate/frame/support/src/traits.rs b/substrate/frame/support/src/traits.rs index f635ed32a124..88ec809a88af 100644 --- a/substrate/frame/support/src/traits.rs +++ b/substrate/frame/support/src/traits.rs @@ -95,8 +95,9 @@ mod storage; #[cfg(feature = "experimental")] pub use storage::MaybeConsideration; pub use storage::{ - Consideration, Footprint, Incrementable, Instance, LinearStoragePrice, PartialStorageInfoTrait, - StorageInfo, StorageInfoTrait, StorageInstance, TrackedStorageKey, WhitelistedStorageKeys, + Consideration, ConstantStoragePrice, Footprint, Incrementable, Instance, LinearStoragePrice, + PartialStorageInfoTrait, StorageInfo, StorageInfoTrait, StorageInstance, TrackedStorageKey, + WhitelistedStorageKeys, }; mod dispatch; diff --git a/substrate/frame/support/src/traits/storage.rs b/substrate/frame/support/src/traits/storage.rs index 2b8e43707389..676b73e03d3c 100644 --- a/substrate/frame/support/src/traits/storage.rs +++ b/substrate/frame/support/src/traits/storage.rs @@ -200,6 +200,18 @@ where } } +/// Constant `Price` regardless of the given [`Footprint`]. +pub struct ConstantStoragePrice(PhantomData<(Price, Balance)>); +impl Convert for ConstantStoragePrice +where + Price: Get, + Balance: From + sp_runtime::Saturating, +{ + fn convert(_: Footprint) -> Balance { + Price::get() + } +} + /// Some sort of cost taken from account temporarily in order to offset the cost to the chain of /// holding some data [`Footprint`] in state. /// From eef21d748bad14b3d040e02802fb2801e85c00fc Mon Sep 17 00:00:00 2001 From: muharem Date: Thu, 12 Sep 2024 16:52:46 +0200 Subject: [PATCH 143/159] remove pool_stakers storage item when it is empty --- substrate/frame/asset-rewards/src/lib.rs | 14 ++++++++++++-- substrate/frame/asset-rewards/src/tests.rs | 12 ++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 03da7ae61fe8..fb438f04029a 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -550,7 +550,12 @@ pub mod pallet { // Update PoolStakers. staker_info.amount.ensure_sub_assign(amount)?; - PoolStakers::::insert(pool_id, &caller, staker_info); + + if staker_info.amount.is_zero() && staker_info.rewards.is_zero() { + PoolStakers::::remove(&pool_id, &caller); + } else { + PoolStakers::::insert(&pool_id, &caller, staker_info); + } // Emit event. Self::deposit_event(Event::Unstaked { caller, pool_id, amount }); @@ -589,7 +594,12 @@ pub mod pallet { // Reset staker rewards. staker_info.rewards = 0u32.into(); - PoolStakers::::insert(pool_id, &staker, staker_info); + + if staker_info.amount.is_zero() { + PoolStakers::::remove(&pool_id, &staker); + } else { + PoolStakers::::insert(&pool_id, &staker, staker_info); + } Ok(()) } diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 52ebc3f669ca..437a53416449 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -78,8 +78,12 @@ fn assert_hypothetically_earned( // Harvest the rewards. assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker), pool_id)); - // Sanity check: staker rewards are reset to 0. - assert_eq!(PoolStakers::::get(pool_id, staker).unwrap().rewards, 0); + // Sanity check: staker rewards are reset to 0 if some `amount` is still staked, otherwise + // the storage item removed. + if let Some(staker_pool) = PoolStakers::::get(pool_id, staker) { + assert!(staker_pool.rewards == 0); + assert!(staker_pool.amount > 0); + } // Check that the staker has earned the expected amount. let balance_after = @@ -530,8 +534,8 @@ mod unstake { // User unstakes remaining tokens assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(user), pool_id, 500)); - // Check that the user's staked amount is zero - assert_eq!(PoolStakers::::get(pool_id, user).unwrap().amount, 0); + // Check that the storage items is removed since stake amount and rewards are zero. + assert!(PoolStakers::::get(pool_id, user).is_none()); // Check that the pool's total tokens staked is zero assert_eq!(Pools::::get(pool_id).unwrap().total_tokens_staked, 0); From 0c1cff624d20b700e65d7945349489657d06f9fb Mon Sep 17 00:00:00 2001 From: muharem Date: Fri, 13 Sep 2024 12:22:45 +0200 Subject: [PATCH 144/159] cleanup call --- .../src/weights/pallet_asset_rewards.rs | 4 + .../src/weights/pallet_asset_rewards.rs | 4 + .../frame/asset-rewards/src/benchmarking.rs | 25 ++++++ substrate/frame/asset-rewards/src/lib.rs | 56 ++++++++++++- substrate/frame/asset-rewards/src/tests.rs | 78 +++++++++++++++++++ substrate/frame/asset-rewards/src/weights.rs | 9 +++ 6 files changed, 173 insertions(+), 3 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs index ec7231a1dc0f..15cebb18d4fe 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs @@ -164,4 +164,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } + // TODO: replace with actual weight. + fn cleanup_pool() -> Weight { + Weight::MAX + } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs index 0dc7e2a6b5f2..9e216ed4f80f 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs @@ -164,4 +164,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } + // TODO: replace with actual weight. + fn cleanup_pool() -> Weight { + Weight::MAX + } } diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index bab8ebbec411..5a0e02451bd5 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -323,5 +323,30 @@ mod benchmarks { Ok(()) } + #[benchmark] + fn cleanup_pool() -> Result<(), BenchmarkError> { + let create_origin = create_reward_pool::()?; + let caller = T::CreatePoolOrigin::ensure_origin(create_origin.clone()).unwrap(); + + // deposit rewards tokens to get worth case benchmark. + { + let caller = whitelisted_caller(); + let reward_asset = T::BenchmarkHelper::reward_asset(); + let min_balance = mint_into::(&caller, &reward_asset); + assert_ok!(AssetRewards::::deposit_reward_tokens( + RawOrigin::Signed(caller).into(), + 0, + min_balance + )); + } + + #[extrinsic_call] + _(RawOrigin::Signed(caller), 0); + + assert_last_event::(Event::PoolCleanedUp { pool_id: 0 }.into()); + + Ok(()) + } + impl_benchmark_test_suite!(AssetRewards, crate::mock::new_test_ext(), crate::mock::MockRuntime); } diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index fb438f04029a..e6da89bf2e88 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -178,7 +178,7 @@ pub mod pallet { pallet_prelude::*, traits::{ fungibles::MutateFreeze, - tokens::{AssetId, Preservation}, + tokens::{AssetId, Fortitude, Preservation}, Consideration, Footprint, }, }; @@ -362,6 +362,11 @@ pub mod pallet { /// The new expiry block. new_expiry_block: BlockNumberFor, }, + /// A pool information was cleared after it's completion. + PoolCleanedUp { + /// The cleared pool. + pool_id: PoolId, + }, } #[pallet::error] @@ -384,6 +389,8 @@ pub mod pallet { ExpiryCut, /// The reward rate per block can be only increased. RewardRateCut, + /// The pool still has staked tokens or rewards. + NonEmptyPool, } #[pallet::hooks] @@ -412,8 +419,9 @@ pub mod pallet { /// - `reward_rate_per_block`: the amount of reward tokens distributed per block; /// - `expiry`: the block number at which the pool will cease to accumulate rewards. The /// [`DispatchTime::After`] variant evaluated at the execution time. - /// - `admin`: the account allowed to modify the pool. If `None`, the pool cannot be - /// altered. + /// - `admin`: the account allowed to extend the pool expiration, increase the rewards rate + /// and receive the unutilized reward tokens back after the pool completion. If `None`, + /// the pool cannot be altered. #[pallet::call_index(0)] pub fn create_pool( origin: OriginFor, @@ -724,6 +732,48 @@ pub mod pallet { )?; Ok(()) } + + /// Cleanup a pool. + /// + /// Origin must be the pool admin. + /// + /// Cleanup storage, release any associated storage cost and return the remaining reward + /// tokens to the admin. + #[pallet::call_index(8)] + pub fn cleanup_pool(origin: OriginFor, pool_id: PoolId) -> DispatchResult { + let who = ensure_signed(origin)?; + + let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + let admin = pool_info.admin.as_ref().ok_or(BadOrigin)?; + ensure!(admin == &who, BadOrigin); + + let stakers = PoolStakers::::iter_key_prefix(pool_id).next(); + ensure!(stakers.is_none(), Error::::NonEmptyPool); + + let pool_balance = T::Assets::reducible_balance( + pool_info.reward_asset_id.clone(), + &pool_info.account, + Preservation::Expendable, + Fortitude::Polite, + ); + T::Assets::transfer( + pool_info.reward_asset_id, + &pool_info.account, + &admin, + pool_balance, + Preservation::Expendable, + )?; + + if let Some((who, cost)) = PoolCost::::take(pool_id) { + T::Consideration::drop(cost, &who)?; + } + + Pools::::remove(pool_id); + + Self::deposit_event(Event::PoolCleanedUp { pool_id }); + + Ok(()) + } } impl Pallet { diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 437a53416449..d610f80d49bc 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -19,6 +19,7 @@ use crate::{mock::*, *}; use frame_support::{ assert_err, assert_noop, assert_ok, hypothetically, traits::{ + fungible, fungible::NativeOrWithId, fungibles, tokens::{Fortitude, Preservation}, @@ -1171,6 +1172,83 @@ mod deposit_reward_tokens { } } +mod cleanup_pool { + use super::*; + + #[test] + fn success() { + new_test_ext().execute_with(|| { + let pool_id = 0; + let admin = DEFAULT_ADMIN; + let admin_balance_before = >::balance(&admin); + + create_default_pool(); + assert!(Pools::::get(pool_id).is_some()); + + assert_ok!(StakingRewards::cleanup_pool(RuntimeOrigin::signed(admin), pool_id)); + + assert_eq!( + >::balance(&admin), + // `100_000` initial pool account balance from Genesis config + admin_balance_before + 100_000, + ); + assert_eq!(Pools::::get(pool_id), None); + assert_eq!(PoolStakers::::iter_prefix_values(pool_id).count(), 0); + assert_eq!(PoolCost::::get(pool_id), None); + }); + } + + #[test] + fn success_only_when_pool_empty() { + new_test_ext().execute_with(|| { + let pool_id = 0; + let staker = 20; + let admin = DEFAULT_ADMIN; + + create_default_pool(); + + // stake to prevent pool cleanup + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker), pool_id, 100)); + + assert_noop!( + StakingRewards::cleanup_pool(RuntimeOrigin::signed(admin), pool_id), + Error::::NonEmptyPool + ); + + // unstake partially + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker), pool_id, 50)); + + assert_noop!( + StakingRewards::cleanup_pool(RuntimeOrigin::signed(admin), pool_id), + Error::::NonEmptyPool + ); + + // unstake all + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker), pool_id, 50)); + + assert_ok!(StakingRewards::cleanup_pool(RuntimeOrigin::signed(admin), pool_id),); + + assert_eq!(Pools::::get(pool_id), None); + assert_eq!(PoolStakers::::iter_prefix_values(pool_id).count(), 0); + assert_eq!(PoolCost::::get(pool_id), None); + }); + } + + #[test] + fn fails_on_wrong_origin() { + new_test_ext().execute_with(|| { + let caller = 888; + let pool_id = 0; + create_default_pool(); + + assert_noop!( + StakingRewards::cleanup_pool(RuntimeOrigin::signed(caller), pool_id), + BadOrigin + ); + }); + } +} + /// This integration test /// 1. Considers 2 stakers each staking and unstaking at different intervals, asserts their /// claimable rewards are adjusted as expected, and that harvesting works. diff --git a/substrate/frame/asset-rewards/src/weights.rs b/substrate/frame/asset-rewards/src/weights.rs index ac2c3a6663e8..575bf97d0641 100644 --- a/substrate/frame/asset-rewards/src/weights.rs +++ b/substrate/frame/asset-rewards/src/weights.rs @@ -55,6 +55,7 @@ pub trait WeightInfo { fn set_pool_admin() -> Weight; fn set_pool_expiry_block() -> Weight; fn deposit_reward_tokens() -> Weight; + fn cleanup_pool() -> Weight; } /// Weights for `pallet_asset_rewards` using the Substrate node and recommended hardware. @@ -188,6 +189,10 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } + // TODO: replace with actual weight. + fn cleanup_pool() -> Weight { + Weight::MAX + } } // For backwards compatibility and tests. @@ -320,4 +325,8 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } + // TODO: replace with actual weight. + fn cleanup_pool() -> Weight { + Weight::MAX + } } From a6183a559dd11c3708d0c42958647da587686bad Mon Sep 17 00:00:00 2001 From: muharem Date: Fri, 13 Sep 2024 12:41:09 +0200 Subject: [PATCH 145/159] make admin non optional --- .../frame/asset-rewards/src/benchmarking.rs | 8 +- substrate/frame/asset-rewards/src/lib.rs | 30 +++-- substrate/frame/asset-rewards/src/tests.rs | 107 ++++-------------- 3 files changed, 35 insertions(+), 110 deletions(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 5a0e02451bd5..2780fd65fc89 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -150,7 +150,7 @@ mod benchmarks { assert_last_event::( Event::PoolCreated { creator: caller.clone(), - admin: Some(caller), + admin: caller, staked_asset_id: staked_asset, reward_asset_id: reward_asset, reward_rate_per_block: min_balance, @@ -268,11 +268,9 @@ mod benchmarks { let new_admin: T::AccountId = whitelisted_caller(); #[extrinsic_call] - _(caller_origin as T::RuntimeOrigin, 0, Some(new_admin.clone())); + _(caller_origin as T::RuntimeOrigin, 0, new_admin.clone()); - assert_last_event::( - Event::PoolAdminModified { pool_id: 0, new_admin: Some(new_admin) }.into(), - ); + assert_last_event::(Event::PoolAdminModified { pool_id: 0, new_admin }.into()); Ok(()) } diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index e6da89bf2e88..8a81b343178e 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -37,8 +37,7 @@ //! Care should be taken by the pool operator to keep pool accounts adequately funded with the //! reward asset. //! -//! The pool admin may adjust the pool configuration such as reward rate per block, expiry block, -//! and admin. +//! The pool admin may increase reward rate per block, increase expiry block, and change admin. //! //! ## Disambiguation //! @@ -148,9 +147,7 @@ pub struct PoolInfo { /// The block the pool will cease distributing rewards. expiry_block: BlockNumber, /// The account authorized to manage this pool. - /// - /// If set to `None`, the pool cannot be altered after creation. - admin: Option, + admin: AccountId, /// The total amount of tokens staked in this pool. total_tokens_staked: Balance, /// Total rewards accumulated per token, up to the `last_update_block`. @@ -337,7 +334,7 @@ pub mod pallet { /// The block the pool will cease to accumulate rewards. expiry_block: BlockNumberFor, /// The account allowed to modify the pool. - admin: Option, + admin: T::AccountId, }, /// A pool reward rate was modified by the admin. PoolRewardRateModified { @@ -351,9 +348,7 @@ pub mod pallet { /// The modified pool. pool_id: PoolId, /// The new admin. - /// - /// If `None`, the pool cannot be altered anymore. - new_admin: Option, + new_admin: T::AccountId, }, /// A pool expiry block was modified by the admin. PoolExpiryBlockModified { @@ -421,7 +416,7 @@ pub mod pallet { /// [`DispatchTime::After`] variant evaluated at the execution time. /// - `admin`: the account allowed to extend the pool expiration, increase the rewards rate /// and receive the unutilized reward tokens back after the pool completion. If `None`, - /// the pool cannot be altered. + /// the caller is set as an admin. #[pallet::call_index(0)] pub fn create_pool( origin: OriginFor, @@ -457,6 +452,8 @@ pub mod pallet { let cost = T::Consideration::new(&creator, footprint)?; PoolCost::::insert(pool_id, (creator.clone(), cost)); + let admin = admin.unwrap_or(creator.clone()); + // Create the pool. let pool = PoolInfoFor:: { staked_asset_id: *staked_asset_id.clone(), @@ -627,7 +624,7 @@ pub mod pallet { .or_else(|_| ensure_signed(origin))?; let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin.as_ref().map_or(false, |admin| admin == &caller), BadOrigin); + ensure!(pool_info.admin == caller, BadOrigin); ensure!( new_reward_rate_per_block > pool_info.reward_rate_per_block, Error::::RewardRateCut @@ -655,13 +652,13 @@ pub mod pallet { pub fn set_pool_admin( origin: OriginFor, pool_id: PoolId, - new_admin: Option, + new_admin: T::AccountId, ) -> DispatchResult { let caller = T::CreatePoolOrigin::ensure_origin(origin.clone()) .or_else(|_| ensure_signed(origin))?; let mut pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin.as_ref().map_or(false, |admin| admin == &caller), BadOrigin); + ensure!(pool_info.admin == caller, BadOrigin); pool_info.admin = new_admin.clone(); Pools::::insert(pool_id, pool_info); @@ -692,7 +689,7 @@ pub mod pallet { ); let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - ensure!(pool_info.admin.as_ref().map_or(false, |admin| admin == &caller), BadOrigin); + ensure!(pool_info.admin == caller, BadOrigin); ensure!(new_expiry > pool_info.expiry_block, Error::::ExpiryCut); // Always start by updating the pool rewards. @@ -744,8 +741,7 @@ pub mod pallet { let who = ensure_signed(origin)?; let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - let admin = pool_info.admin.as_ref().ok_or(BadOrigin)?; - ensure!(admin == &who, BadOrigin); + ensure!(pool_info.admin == who, BadOrigin); let stakers = PoolStakers::::iter_key_prefix(pool_id).next(); ensure!(stakers.is_none(), Error::::NonEmptyPool); @@ -759,7 +755,7 @@ pub mod pallet { T::Assets::transfer( pool_info.reward_asset_id, &pool_info.account, - &admin, + &pool_info.admin, pool_balance, Preservation::Expendable, )?; diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index d610f80d49bc..1663ce485f64 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -147,7 +147,7 @@ mod create_pool { reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: expected_expiry_block, - admin: Some(PermissionedAccountId::get()), + admin: PermissionedAccountId::get(), }] ); @@ -162,7 +162,7 @@ mod create_pool { reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: expected_expiry_block, - admin: Some(PermissionedAccountId::get()), + admin: PermissionedAccountId::get(), total_tokens_staked: 0, reward_per_token_stored: 0, last_update_block: 0, @@ -196,7 +196,7 @@ mod create_pool { staked_asset_id: staked_asset_id.clone(), reward_asset_id: reward_asset_id.clone(), reward_rate_per_block, - admin: Some(admin), + admin, expiry_block: expected_expiry_block, }] ); @@ -212,7 +212,7 @@ mod create_pool { staked_asset_id: DEFAULT_STAKED_ASSET_ID, reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, - admin: Some(PermissionedAccountId::get()), + admin: PermissionedAccountId::get(), expiry_block: DEFAULT_EXPIRE_AFTER + 10, total_tokens_staked: 0, reward_per_token_stored: 0, @@ -226,7 +226,7 @@ mod create_pool { staked_asset_id, reward_asset_id, reward_rate_per_block, - admin: Some(admin), + admin, total_tokens_staked: 0, expiry_block: expected_expiry_block, reward_per_token_stored: 0, @@ -268,7 +268,7 @@ mod create_pool { reward_asset_id: asset.clone(), reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: expected_expiry_block, - admin: Some(PermissionedAccountId::get()), + admin: PermissionedAccountId::get(), }] ); @@ -283,7 +283,7 @@ mod create_pool { reward_asset_id: asset, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: expected_expiry_block, - admin: Some(PermissionedAccountId::get()), + admin: PermissionedAccountId::get(), total_tokens_staked: 0, reward_per_token_stored: 0, last_update_block: 0, @@ -361,7 +361,7 @@ mod create_pool { } #[test] - fn create_pool_without_admin() { + fn create_pool_with_caller_admin() { new_test_ext().execute_with(|| { assert_eq!(NextPoolId::::get(), 0); @@ -386,15 +386,11 @@ mod create_pool { reward_asset_id: DEFAULT_REWARD_ASSET_ID, reward_rate_per_block: DEFAULT_REWARD_RATE_PER_BLOCK, expiry_block: expected_expiry_block, - admin: None, + admin: PermissionedAccountId::get(), }] ); - assert_eq!(Pools::::get(0).unwrap().admin, None); - assert_noop!( - StakingRewards::set_pool_admin(RuntimeOrigin::root(), 0, None,), - BadOrigin - ); + assert_eq!(Pools::::get(0).unwrap().admin, PermissionedAccountId::get()); }); } } @@ -660,15 +656,15 @@ mod set_pool_admin { assert_ok!(StakingRewards::set_pool_admin( RuntimeOrigin::signed(admin), pool_id, - Some(new_admin), + new_admin, )); // Check state assert_eq!( *events().last().unwrap(), - Event::::PoolAdminModified { pool_id, new_admin: Some(new_admin) } + Event::::PoolAdminModified { pool_id, new_admin } ); - assert_eq!(Pools::::get(pool_id).unwrap().admin, Some(new_admin)); + assert_eq!(Pools::::get(pool_id).unwrap().admin, new_admin); }); } @@ -680,18 +676,14 @@ mod set_pool_admin { create_default_pool_permissioned_admin(); // Modify the pool admin - assert_ok!(StakingRewards::set_pool_admin( - RuntimeOrigin::root(), - pool_id, - Some(new_admin) - )); + assert_ok!(StakingRewards::set_pool_admin(RuntimeOrigin::root(), pool_id, new_admin)); // Check state assert_eq!( *events().last().unwrap(), - Event::::PoolAdminModified { pool_id, new_admin: Some(new_admin) } + Event::::PoolAdminModified { pool_id, new_admin } ); - assert_eq!(Pools::::get(pool_id).unwrap().admin, Some(new_admin)); + assert_eq!(Pools::::get(pool_id).unwrap().admin, new_admin); }); } @@ -706,7 +698,7 @@ mod set_pool_admin { StakingRewards::set_pool_admin( RuntimeOrigin::signed(admin), non_existent_pool_id, - Some(new_admin) + new_admin ), Error::::NonExistentPool ); @@ -725,31 +717,12 @@ mod set_pool_admin { StakingRewards::set_pool_admin( RuntimeOrigin::signed(non_admin), pool_id, - Some(new_admin) + new_admin ), BadOrigin ); }); } - - #[test] - fn clear_admin() { - new_test_ext().execute_with(|| { - let admin = 1; - let pool_id = 0; - create_default_pool(); - - assert_ok!( - StakingRewards::set_pool_admin(RuntimeOrigin::signed(admin), pool_id, None,) - ); - - assert_eq!(Pools::::get(pool_id).unwrap().admin, None); - assert_noop!( - StakingRewards::set_pool_admin(RuntimeOrigin::signed(admin), pool_id, None,), - BadOrigin - ); - }); - } } mod set_pool_expiry_block { @@ -919,29 +892,6 @@ mod set_pool_expiry_block { ); }); } - - #[test] - fn fails_for_pool_without_admin() { - new_test_ext().execute_with(|| { - assert_ok!(StakingRewards::create_pool( - RuntimeOrigin::root(), - Box::new(DEFAULT_STAKED_ASSET_ID.clone()), - Box::new(DEFAULT_REWARD_ASSET_ID.clone()), - DEFAULT_REWARD_RATE_PER_BLOCK, - DispatchTime::After(DEFAULT_EXPIRE_AFTER), - None, - )); - - assert_err!( - StakingRewards::set_pool_expiry_block( - RuntimeOrigin::root(), - 0, - DispatchTime::After(200) - ), - BadOrigin - ); - }); - } } mod set_pool_reward_rate_per_block { @@ -1080,25 +1030,6 @@ mod set_pool_reward_rate_per_block { }); } - #[test] - fn fails_for_pool_without_admin() { - new_test_ext().execute_with(|| { - assert_ok!(StakingRewards::create_pool( - RuntimeOrigin::root(), - Box::new(DEFAULT_STAKED_ASSET_ID.clone()), - Box::new(DEFAULT_REWARD_ASSET_ID.clone()), - DEFAULT_REWARD_RATE_PER_BLOCK, - DispatchTime::After(DEFAULT_EXPIRE_AFTER), - None, - )); - - assert_err!( - StakingRewards::set_pool_reward_rate_per_block(RuntimeOrigin::root(), 0, 200), - BadOrigin - ); - }); - } - #[test] fn fails_to_decrease() { new_test_ext().execute_with(|| { @@ -1407,7 +1338,7 @@ fn integration() { reward_asset_id, reward_rate_per_block: 100, expiry_block: 25, - admin: Some(admin), + admin, }, Event::Staked { caller: staker1, pool_id, amount: 100 }, Event::Staked { caller: staker2, pool_id, amount: 100 }, From 55ed586ea1a1d525bc291bee749c8cf7f3452ad3 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Fri, 13 Sep 2024 12:19:00 +0000 Subject: [PATCH 146/159] ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=asset-hub-rococo --runtime_dir=assets --target_dir=cumulus --pallet=pallet_asset_rewards --- .../src/weights/pallet_asset_rewards.rs | 194 +++++++++++------- 1 file changed, 120 insertions(+), 74 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs index 15cebb18d4fe..184babb8686f 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_asset_rewards` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-04-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-09-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-obbyq9g6-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -48,124 +48,170 @@ use core::marker::PhantomData; /// Weight functions for `pallet_asset_rewards`. pub struct WeightInfo(PhantomData); impl pallet_asset_rewards::WeightInfo for WeightInfo { - /// Storage: `ForeignAssets::Asset` (r:1 w:0) - /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:2 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::NextPoolId` (r:1 w:1) - /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::PoolCost` (r:0 w:1) + /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::Pools` (r:0 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) fn create_pool() -> Weight { // Proof Size summary in bytes: - // Measured: `189` - // Estimated: `4273` - // Minimum execution time: 15_379_000 picoseconds. - Weight::from_parts(16_182_000, 0) - .saturating_add(Weight::from_parts(0, 4273)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `358` + // Estimated: `6360` + // Minimum execution time: 60_981_000 picoseconds. + Weight::from_parts(62_812_000, 0) + .saturating_add(Weight::from_parts(0, 6360)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) - /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::Freezes` (r:1 w:1) + /// Proof: `AssetsFreezer::Freezes` (`max_values`: None, `max_size`: Some(87), added: 2562, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:0) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:1) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn stake() -> Weight { // Proof Size summary in bytes: - // Measured: `242` - // Estimated: `3707` - // Minimum execution time: 18_711_000 picoseconds. - Weight::from_parts(19_313_000, 0) - .saturating_add(Weight::from_parts(0, 3707)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `872` + // Estimated: `4809` + // Minimum execution time: 55_988_000 picoseconds. + Weight::from_parts(56_817_000, 0) + .saturating_add(Weight::from_parts(0, 4809)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) - /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::Freezes` (r:1 w:1) + /// Proof: `AssetsFreezer::Freezes` (`max_values`: None, `max_size`: Some(87), added: 2562, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:0) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:1) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn unstake() -> Weight { // Proof Size summary in bytes: - // Measured: `382` - // Estimated: `3847` - // Minimum execution time: 22_244_000 picoseconds. - Weight::from_parts(22_756_000, 0) - .saturating_add(Weight::from_parts(0, 3847)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `872` + // Estimated: `4809` + // Minimum execution time: 57_003_000 picoseconds. + Weight::from_parts(58_191_000, 0) + .saturating_add(Weight::from_parts(0, 4809)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) - /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ForeignAssets::Asset` (r:1 w:1) - /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) - /// Storage: `ForeignAssets::Account` (r:2 w:2) - /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:0) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn harvest_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `880` - // Estimated: `7404` - // Minimum execution time: 63_048_000 picoseconds. - Weight::from_parts(64_136_000, 0) - .saturating_add(Weight::from_parts(0, 7404)) - .saturating_add(T::DbWeight::get().reads(5)) + // Measured: `1072` + // Estimated: `6208` + // Minimum execution time: 78_620_000 picoseconds. + Weight::from_parts(80_355_000, 0) + .saturating_add(Weight::from_parts(0, 6208)) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) fn set_pool_reward_rate_per_block() -> Weight { // Proof Size summary in bytes: - // Measured: `242` - // Estimated: `3707` - // Minimum execution time: 14_068_000 picoseconds. - Weight::from_parts(14_396_000, 0) - .saturating_add(Weight::from_parts(0, 3707)) + // Measured: `318` + // Estimated: `4809` + // Minimum execution time: 16_823_000 picoseconds. + Weight::from_parts(17_233_000, 0) + .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) fn set_pool_admin() -> Weight { // Proof Size summary in bytes: - // Measured: `242` - // Estimated: `3707` - // Minimum execution time: 13_948_000 picoseconds. - Weight::from_parts(14_414_000, 0) - .saturating_add(Weight::from_parts(0, 3707)) + // Measured: `318` + // Estimated: `4809` + // Minimum execution time: 16_067_000 picoseconds. + Weight::from_parts(17_025_000, 0) + .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) fn set_pool_expiry_block() -> Weight { // Proof Size summary in bytes: - // Measured: `242` - // Estimated: `3707` - // Minimum execution time: 14_677_000 picoseconds. - Weight::from_parts(15_052_000, 0) - .saturating_add(Weight::from_parts(0, 3707)) + // Measured: `318` + // Estimated: `4809` + // Minimum execution time: 17_472_000 picoseconds. + Weight::from_parts(18_036_000, 0) + .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ForeignAssets::Asset` (r:1 w:1) - /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) - /// Storage: `ForeignAssets::Account` (r:2 w:2) - /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:0) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn deposit_reward_tokens() -> Weight { // Proof Size summary in bytes: - // Measured: `766` - // Estimated: `7404` - // Minimum execution time: 52_312_000 picoseconds. - Weight::from_parts(53_272_000, 0) - .saturating_add(Weight::from_parts(0, 7404)) - .saturating_add(T::DbWeight::get().reads(5)) + // Measured: `747` + // Estimated: `6208` + // Minimum execution time: 62_101_000 picoseconds. + Weight::from_parts(63_647_000, 0) + .saturating_add(Weight::from_parts(0, 6208)) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } - // TODO: replace with actual weight. + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:0) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:1) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::PoolCost` (r:1 w:1) + /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(85), added: 2560, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::Freezes` (r:0 w:1) + /// Proof: `AssetsFreezer::Freezes` (`max_values`: None, `max_size`: Some(87), added: 2562, mode: `MaxEncodedLen`) fn cleanup_pool() -> Weight { - Weight::MAX + // Proof Size summary in bytes: + // Measured: `1105` + // Estimated: `6208` + // Minimum execution time: 121_326_000 picoseconds. + Weight::from_parts(124_201_000, 0) + .saturating_add(Weight::from_parts(0, 6208)) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(10)) } } From 0562679f4e57cf1ecc1167032456f139bd8840c8 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Fri, 13 Sep 2024 14:09:13 +0000 Subject: [PATCH 147/159] ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=asset-hub-westend --runtime_dir=assets --target_dir=cumulus --pallet=pallet_asset_rewards --- .../src/weights/pallet_asset_rewards.rs | 194 +++++++++++------- 1 file changed, 120 insertions(+), 74 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs index 9e216ed4f80f..ee52ba6e7074 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_asset_rewards` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-04-11, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-09-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-obbyq9g6-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -48,124 +48,170 @@ use core::marker::PhantomData; /// Weight functions for `pallet_asset_rewards`. pub struct WeightInfo(PhantomData); impl pallet_asset_rewards::WeightInfo for WeightInfo { - /// Storage: `ForeignAssets::Asset` (r:1 w:0) - /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:2 w:0) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::NextPoolId` (r:1 w:1) - /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::NextPoolId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::PoolCost` (r:0 w:1) + /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::Pools` (r:0 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) fn create_pool() -> Weight { // Proof Size summary in bytes: - // Measured: `189` - // Estimated: `4273` - // Minimum execution time: 16_850_000 picoseconds. - Weight::from_parts(17_383_000, 0) - .saturating_add(Weight::from_parts(0, 4273)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `392` + // Estimated: `6360` + // Minimum execution time: 60_753_000 picoseconds. + Weight::from_parts(61_702_000, 0) + .saturating_add(Weight::from_parts(0, 6360)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) - /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::Freezes` (r:1 w:1) + /// Proof: `AssetsFreezer::Freezes` (`max_values`: None, `max_size`: Some(87), added: 2562, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:0) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:1) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn stake() -> Weight { // Proof Size summary in bytes: - // Measured: `242` - // Estimated: `3707` - // Minimum execution time: 19_374_000 picoseconds. - Weight::from_parts(19_732_000, 0) - .saturating_add(Weight::from_parts(0, 3707)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `906` + // Estimated: `4809` + // Minimum execution time: 52_703_000 picoseconds. + Weight::from_parts(53_986_000, 0) + .saturating_add(Weight::from_parts(0, 4809)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) - /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::Freezes` (r:1 w:1) + /// Proof: `AssetsFreezer::Freezes` (`max_values`: None, `max_size`: Some(87), added: 2562, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:0) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:1) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn unstake() -> Weight { // Proof Size summary in bytes: - // Measured: `382` - // Estimated: `3847` - // Minimum execution time: 22_934_000 picoseconds. - Weight::from_parts(23_471_000, 0) - .saturating_add(Weight::from_parts(0, 3847)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `906` + // Estimated: `4809` + // Minimum execution time: 54_053_000 picoseconds. + Weight::from_parts(54_983_000, 0) + .saturating_add(Weight::from_parts(0, 4809)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) - /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ForeignAssets::Asset` (r:1 w:1) - /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) - /// Storage: `ForeignAssets::Account` (r:2 w:2) - /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:0) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn harvest_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `880` - // Estimated: `7404` - // Minimum execution time: 62_531_000 picoseconds. - Weight::from_parts(63_845_000, 0) - .saturating_add(Weight::from_parts(0, 7404)) - .saturating_add(T::DbWeight::get().reads(5)) + // Measured: `1106` + // Estimated: `6208` + // Minimum execution time: 79_306_000 picoseconds. + Weight::from_parts(81_088_000, 0) + .saturating_add(Weight::from_parts(0, 6208)) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) fn set_pool_reward_rate_per_block() -> Weight { // Proof Size summary in bytes: - // Measured: `242` - // Estimated: `3707` - // Minimum execution time: 15_120_000 picoseconds. - Weight::from_parts(15_579_000, 0) - .saturating_add(Weight::from_parts(0, 3707)) + // Measured: `318` + // Estimated: `4809` + // Minimum execution time: 17_439_000 picoseconds. + Weight::from_parts(18_179_000, 0) + .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) fn set_pool_admin() -> Weight { // Proof Size summary in bytes: - // Measured: `242` - // Estimated: `3707` - // Minimum execution time: 14_979_000 picoseconds. - Weight::from_parts(15_414_000, 0) - .saturating_add(Weight::from_parts(0, 3707)) + // Measured: `318` + // Estimated: `4809` + // Minimum execution time: 15_893_000 picoseconds. + Weight::from_parts(16_410_000, 0) + .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) fn set_pool_expiry_block() -> Weight { // Proof Size summary in bytes: - // Measured: `242` - // Estimated: `3707` - // Minimum execution time: 16_097_000 picoseconds. - Weight::from_parts(18_616_000, 0) - .saturating_add(Weight::from_parts(0, 3707)) + // Measured: `318` + // Estimated: `4809` + // Minimum execution time: 18_559_000 picoseconds. + Weight::from_parts(19_170_000, 0) + .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `ForeignAssets::Asset` (r:1 w:1) - /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`) - /// Storage: `ForeignAssets::Account` (r:2 w:2) - /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:0) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn deposit_reward_tokens() -> Weight { // Proof Size summary in bytes: - // Measured: `766` - // Estimated: `7404` - // Minimum execution time: 52_754_000 picoseconds. - Weight::from_parts(53_628_000, 0) - .saturating_add(Weight::from_parts(0, 7404)) - .saturating_add(T::DbWeight::get().reads(5)) + // Measured: `781` + // Estimated: `6208` + // Minimum execution time: 62_407_000 picoseconds. + Weight::from_parts(63_858_000, 0) + .saturating_add(Weight::from_parts(0, 6208)) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } - // TODO: replace with actual weight. + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(1344), added: 3819, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:0) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:1) + /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::PoolCost` (r:1 w:1) + /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) + /// Storage: `AssetsFreezer::Freezes` (r:0 w:1) + /// Proof: `AssetsFreezer::Freezes` (`max_values`: None, `max_size`: Some(87), added: 2562, mode: `MaxEncodedLen`) fn cleanup_pool() -> Weight { - Weight::MAX + // Proof Size summary in bytes: + // Measured: `1139` + // Estimated: `6208` + // Minimum execution time: 120_522_000 picoseconds. + Weight::from_parts(123_335_000, 0) + .saturating_add(Weight::from_parts(0, 6208)) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(10)) } } From 949760ed96c758611f8715854da82f86cd7ebc4b Mon Sep 17 00:00:00 2001 From: muharem Date: Tue, 17 Sep 2024 11:45:33 +0200 Subject: [PATCH 148/159] westend send xcm origin includes signed origin --- polkadot/runtime/westend/src/xcm_config.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index 4237dfb09ba1..0905a820e5d3 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -274,7 +274,10 @@ impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; // Note that this configuration of `SendXcmOrigin` is different from the one present in // production. - type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin< + RuntimeOrigin, + (LocalPalletOriginToLocation, LocalOriginToLocation), + >; type XcmRouter = XcmRouter; // Anyone can execute XCM messages locally. type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; From 561144153e4f1d7a9bca8576567a05a8833cd870 Mon Sep 17 00:00:00 2001 From: muharem Date: Tue, 17 Sep 2024 12:39:11 +0200 Subject: [PATCH 149/159] unstake and harvest calls permissionless when a pool is expired --- .../frame/asset-rewards/src/benchmarking.rs | 19 ++- substrate/frame/asset-rewards/src/lib.rs | 59 +++++-- substrate/frame/asset-rewards/src/tests.rs | 145 +++++++++++++++--- 3 files changed, 180 insertions(+), 43 deletions(-) diff --git a/substrate/frame/asset-rewards/src/benchmarking.rs b/substrate/frame/asset-rewards/src/benchmarking.rs index 2780fd65fc89..5605804dd20e 100644 --- a/substrate/frame/asset-rewards/src/benchmarking.rs +++ b/substrate/frame/asset-rewards/src/benchmarking.rs @@ -180,9 +180,7 @@ mod benchmarks { #[extrinsic_call] _(RawOrigin::Signed(staker.clone()), 0, min_balance); - assert_last_event::( - Event::Staked { caller: staker, pool_id: 0, amount: min_balance }.into(), - ); + assert_last_event::(Event::Staked { staker, pool_id: 0, amount: min_balance }.into()); Ok(()) } @@ -201,10 +199,11 @@ mod benchmarks { )); #[extrinsic_call] - _(RawOrigin::Signed(staker.clone()), 0, min_balance); + _(RawOrigin::Signed(staker.clone()), 0, min_balance, None); assert_last_event::( - Event::Unstaked { caller: staker, pool_id: 0, amount: min_balance }.into(), + Event::Unstaked { caller: staker.clone(), staker, pool_id: 0, amount: min_balance } + .into(), ); Ok(()) @@ -228,10 +227,16 @@ mod benchmarks { System::::set_block_number(System::::block_number() + BlockNumberFor::::one()); #[extrinsic_call] - _(RawOrigin::Signed(staker.clone()), 0); + _(RawOrigin::Signed(staker.clone()), 0, None); assert_last_event::( - Event::RewardsHarvested { staker, pool_id: 0, amount: min_reward_balance }.into(), + Event::RewardsHarvested { + caller: staker.clone(), + staker, + pool_id: 0, + amount: min_reward_balance, + } + .into(), ); Ok(()) diff --git a/substrate/frame/asset-rewards/src/lib.rs b/substrate/frame/asset-rewards/src/lib.rs index 8a81b343178e..4ce73e9febf9 100644 --- a/substrate/frame/asset-rewards/src/lib.rs +++ b/substrate/frame/asset-rewards/src/lib.rs @@ -295,7 +295,7 @@ pub mod pallet { /// An account staked some tokens in a pool. Staked { /// The account that staked assets. - caller: T::AccountId, + staker: T::AccountId, /// The pool. pool_id: PoolId, /// The staked asset amount. @@ -303,8 +303,10 @@ pub mod pallet { }, /// An account unstaked some tokens from a pool. Unstaked { - /// The account that unstaked assets. + /// The account that signed transaction. caller: T::AccountId, + /// The account that unstaked assets. + staker: T::AccountId, /// The pool. pool_id: PoolId, /// The unstaked asset amount. @@ -312,6 +314,8 @@ pub mod pallet { }, /// An account harvested some rewards. RewardsHarvested { + /// The account that signed transaction. + caller: T::AccountId, /// The staker whos rewards were harvested. staker: T::AccountId, /// The pool. @@ -491,18 +495,18 @@ pub mod pallet { /// A freeze is placed on the staked tokens. #[pallet::call_index(1)] pub fn stake(origin: OriginFor, pool_id: PoolId, amount: T::Balance) -> DispatchResult { - let caller = ensure_signed(origin)?; + let staker = ensure_signed(origin)?; // Always start by updating staker and pool rewards. let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - let staker_info = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); + let staker_info = PoolStakers::::get(pool_id, &staker).unwrap_or_default(); let (mut pool_info, mut staker_info) = Self::update_pool_and_staker_rewards(&pool_info, &staker_info)?; T::AssetsFreezer::increase_frozen( pool_info.staked_asset_id.clone(), &FreezeReason::Staked.into(), - &caller, + &staker, amount, )?; @@ -513,10 +517,10 @@ pub mod pallet { // Update PoolStakers. staker_info.amount.ensure_add_assign(amount)?; - PoolStakers::::insert(pool_id, &caller, staker_info); + PoolStakers::::insert(pool_id, &staker, staker_info); // Emit event. - Self::deposit_event(Event::Staked { caller, pool_id, amount }); + Self::deposit_event(Event::Staked { staker, pool_id, amount }); Ok(()) } @@ -524,17 +528,28 @@ pub mod pallet { /// Unstake tokens from a pool. /// /// Removes the freeze on the staked tokens. + /// + /// Parameters: + /// - origin: must be the `staker` if the pool is still active. Otherwise, any account. + /// - pool_id: the pool to unstake from. + /// - amount: the amount of tokens to unstake. + /// - staker: the account to unstake from. If `None`, the caller is used. #[pallet::call_index(2)] pub fn unstake( origin: OriginFor, pool_id: PoolId, amount: T::Balance, + staker: Option, ) -> DispatchResult { let caller = ensure_signed(origin)?; + let staker = staker.unwrap_or(caller.clone()); // Always start by updating the pool rewards. let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; - let staker_info = PoolStakers::::get(pool_id, &caller).unwrap_or_default(); + let now = frame_system::Pallet::::block_number(); + ensure!(now > pool_info.expiry_block || caller == staker, BadOrigin); + + let staker_info = PoolStakers::::get(pool_id, &staker).unwrap_or_default(); let (mut pool_info, mut staker_info) = Self::update_pool_and_staker_rewards(&pool_info, &staker_info)?; @@ -545,7 +560,7 @@ pub mod pallet { T::AssetsFreezer::decrease_frozen( pool_info.staked_asset_id.clone(), &FreezeReason::Staked.into(), - &caller, + &staker, amount, )?; @@ -557,24 +572,37 @@ pub mod pallet { staker_info.amount.ensure_sub_assign(amount)?; if staker_info.amount.is_zero() && staker_info.rewards.is_zero() { - PoolStakers::::remove(&pool_id, &caller); + PoolStakers::::remove(&pool_id, &staker); } else { - PoolStakers::::insert(&pool_id, &caller, staker_info); + PoolStakers::::insert(&pool_id, &staker, staker_info); } // Emit event. - Self::deposit_event(Event::Unstaked { caller, pool_id, amount }); + Self::deposit_event(Event::Unstaked { caller, staker, pool_id, amount }); Ok(()) } - /// Harvest unclaimed pool rewards for the caller. + /// Harvest unclaimed pool rewards. + /// + /// Parameters: + /// - origin: must be the `staker` if the pool is still active. Otherwise, any account. + /// - pool_id: the pool to harvest from. + /// - staker: the account for which to harvest rewards. If `None`, the caller is used. #[pallet::call_index(3)] - pub fn harvest_rewards(origin: OriginFor, pool_id: PoolId) -> DispatchResult { - let staker = ensure_signed(origin)?; + pub fn harvest_rewards( + origin: OriginFor, + pool_id: PoolId, + staker: Option, + ) -> DispatchResult { + let caller = ensure_signed(origin)?; + let staker = staker.unwrap_or(caller.clone()); // Always start by updating the pool and staker rewards. let pool_info = Pools::::get(pool_id).ok_or(Error::::NonExistentPool)?; + let now = frame_system::Pallet::::block_number(); + ensure!(now > pool_info.expiry_block || caller == staker, BadOrigin); + let staker_info = PoolStakers::::get(pool_id, &staker).ok_or(Error::::NonExistentStaker)?; let (pool_info, mut staker_info) = @@ -592,6 +620,7 @@ pub mod pallet { // Emit event. Self::deposit_event(Event::RewardsHarvested { + caller, staker: staker.clone(), pool_id, amount: staker_info.rewards, diff --git a/substrate/frame/asset-rewards/src/tests.rs b/substrate/frame/asset-rewards/src/tests.rs index 1663ce485f64..399d6a54c939 100644 --- a/substrate/frame/asset-rewards/src/tests.rs +++ b/substrate/frame/asset-rewards/src/tests.rs @@ -77,7 +77,7 @@ fn assert_hypothetically_earned( <::Assets>::balance(reward_asset_id.clone(), &staker); // Harvest the rewards. - assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker), pool_id)); + assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker), pool_id, None),); // Sanity check: staker rewards are reset to 0 if some `amount` is still staked, otherwise // the storage item removed. @@ -420,7 +420,7 @@ mod stake { // Event is emitted. assert_eq!( *events().last().unwrap(), - Event::::Staked { caller: user, amount: 1000, pool_id: 0 } + Event::::Staked { staker: user, amount: 1000, pool_id: 0 } ); // Check that the pool's total tokens staked is updated @@ -444,7 +444,7 @@ mod stake { // Event is emitted. assert_eq!( *events().last().unwrap(), - Event::::Staked { caller: user, amount: 500, pool_id: 0 } + Event::::Staked { staker: user, amount: 500, pool_id: 0 } ); // Check that the user's staked amount is updated @@ -514,12 +514,17 @@ mod unstake { assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(user), pool_id, 1000)); // User unstakes tokens - assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(user), pool_id, 500)); + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(user), pool_id, 500, None)); // Event is emitted. assert_eq!( *events().last().unwrap(), - Event::::Unstaked { caller: user, amount: 500, pool_id: 0 } + Event::::Unstaked { + caller: user, + staker: user, + amount: 500, + pool_id: 0 + } ); // Check that the user's staked amount is updated @@ -529,7 +534,7 @@ mod unstake { assert_eq!(Pools::::get(pool_id).unwrap().total_tokens_staked, 500); // User unstakes remaining tokens - assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(user), pool_id, 500)); + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(user), pool_id, 500, None)); // Check that the storage items is removed since stake amount and rewards are zero. assert!(PoolStakers::::get(pool_id, user).is_none()); @@ -539,6 +544,42 @@ mod unstake { }); } + #[test] + fn unstake_for_other() { + new_test_ext().execute_with(|| { + let staker = 1; + let caller = 2; + let pool_id = 0; + let init_block = System::block_number(); + + create_default_pool(); + + // User stakes tokens + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker), pool_id, 1000)); + + // Fails to unstake for other since pool is still active + assert_noop!( + StakingRewards::unstake(RuntimeOrigin::signed(caller), pool_id, 500, Some(staker)), + BadOrigin, + ); + + System::set_block_number(init_block + DEFAULT_EXPIRE_AFTER + 1); + + assert_ok!(StakingRewards::unstake( + RuntimeOrigin::signed(caller), + pool_id, + 500, + Some(staker) + )); + + // Event is emitted. + assert_eq!( + *events().last().unwrap(), + Event::::Unstaked { caller, staker, amount: 500, pool_id: 0 } + ); + }); + } + #[test] fn fails_for_non_existent_pool() { new_test_ext().execute_with(|| { @@ -547,7 +588,12 @@ mod unstake { // User tries to unstake tokens from a non-existent pool assert_err!( - StakingRewards::unstake(RuntimeOrigin::signed(user), non_existent_pool_id, 500), + StakingRewards::unstake( + RuntimeOrigin::signed(user), + non_existent_pool_id, + 500, + None + ), Error::::NonExistentPool ); }); @@ -565,7 +611,7 @@ mod unstake { // User tries to unstake more tokens than they have staked assert_err!( - StakingRewards::unstake(RuntimeOrigin::signed(user), pool_id, 1500), + StakingRewards::unstake(RuntimeOrigin::signed(user), pool_id, 1500, None), Error::::NotEnoughTokens ); }); @@ -591,7 +637,11 @@ mod harvest_rewards { System::set_block_number(20); let balance_before: ::Balance = <::Assets>::balance(reward_asset_id.clone(), &staker); - assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker), pool_id,)); + assert_ok!(StakingRewards::harvest_rewards( + RuntimeOrigin::signed(staker), + pool_id, + None + )); let balance_after = <::Assets>::balance(reward_asset_id.clone(), &staker); @@ -603,6 +653,7 @@ mod harvest_rewards { assert_eq!( *events().last().unwrap(), Event::::RewardsHarvested { + caller: staker, staker, pool_id, amount: 10 * Pools::::get(pool_id).unwrap().reward_rate_per_block @@ -611,6 +662,53 @@ mod harvest_rewards { }); } + #[test] + fn harvest_for_other() { + new_test_ext().execute_with(|| { + let caller = 2; + let staker = 1; + let pool_id = 0; + let init_block = System::block_number(); + + create_default_pool(); + + // Stake + System::set_block_number(10); + assert_ok!(StakingRewards::stake(RuntimeOrigin::signed(staker), pool_id, 1000)); + + System::set_block_number(20); + + // Fails to harvest for staker since pool is still active + assert_noop!( + StakingRewards::harvest_rewards( + RuntimeOrigin::signed(caller), + pool_id, + Some(staker) + ), + BadOrigin + ); + + System::set_block_number(init_block + DEFAULT_EXPIRE_AFTER + 1); + + // Harvest for staker + assert_ok!(StakingRewards::harvest_rewards( + RuntimeOrigin::signed(caller), + pool_id, + Some(staker), + )); + + assert!(matches!( + events().last().unwrap(), + Event::::RewardsHarvested { + caller, + staker, + pool_id, + .. + } if caller == caller && staker == staker && pool_id == pool_id + )); + }); + } + #[test] fn fails_for_non_existent_staker() { new_test_ext().execute_with(|| { @@ -618,7 +716,11 @@ mod harvest_rewards { create_default_pool(); assert_err!( - StakingRewards::harvest_rewards(RuntimeOrigin::signed(non_existent_staker), 0,), + StakingRewards::harvest_rewards( + RuntimeOrigin::signed(non_existent_staker), + 0, + None + ), Error::::NonExistentStaker ); }); @@ -634,6 +736,7 @@ mod harvest_rewards { StakingRewards::harvest_rewards( RuntimeOrigin::signed(staker), non_existent_pool_id, + None, ), Error::::NonExistentPool ); @@ -1147,7 +1250,7 @@ mod cleanup_pool { ); // unstake partially - assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker), pool_id, 50)); + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker), pool_id, 50, None)); assert_noop!( StakingRewards::cleanup_pool(RuntimeOrigin::signed(admin), pool_id), @@ -1155,7 +1258,7 @@ mod cleanup_pool { ); // unstake all - assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker), pool_id, 50)); + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker), pool_id, 50, None)); assert_ok!(StakingRewards::cleanup_pool(RuntimeOrigin::signed(admin), pool_id),); @@ -1248,7 +1351,7 @@ fn integration() { // Block 22: Staker 1 unstakes 100 tokens. System::set_block_number(22); - assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker1), pool_id, 100)); + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker1), pool_id, 100, None)); // - Staker 1 has earned 1016 (350 + 66.66 * 10) tokens. // - Staker 2 has earned 483 (150 + 33.33 * 10) tokens. // - Staker 1 is earning 50 tokens per block. @@ -1258,7 +1361,7 @@ fn integration() { // Block 23: Staker 1 unstakes 100 tokens. System::set_block_number(23); - assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker1), pool_id, 100)); + assert_ok!(StakingRewards::unstake(RuntimeOrigin::signed(staker1), pool_id, 100, None)); // - Staker 1 has earned 1065 (1015 + 50) tokens. // - Staker 2 has earned 533 (483 + 50) tokens. // - Staker 1 is earning 0 tokens per block. @@ -1315,7 +1418,7 @@ fn integration() { // Get the pre-harvest balance. let balance_before: ::Balance = <::Assets>::balance(reward_asset_id.clone(), &staker2); - assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker2), pool_id)); + assert_ok!(StakingRewards::harvest_rewards(RuntimeOrigin::signed(staker2), pool_id, None)); let balance_after = <::Assets>::balance(reward_asset_id.clone(), &staker2); assert_eq!(balance_after - balance_before, 1433u128); @@ -1340,14 +1443,14 @@ fn integration() { expiry_block: 25, admin, }, - Event::Staked { caller: staker1, pool_id, amount: 100 }, - Event::Staked { caller: staker2, pool_id, amount: 100 }, - Event::Staked { caller: staker1, pool_id, amount: 100 }, - Event::Unstaked { caller: staker1, pool_id, amount: 100 }, - Event::Unstaked { caller: staker1, pool_id, amount: 100 }, + Event::Staked { staker: staker1, pool_id, amount: 100 }, + Event::Staked { staker: staker2, pool_id, amount: 100 }, + Event::Staked { staker: staker1, pool_id, amount: 100 }, + Event::Unstaked { caller: staker1, staker: staker1, pool_id, amount: 100 }, + Event::Unstaked { caller: staker1, staker: staker1, pool_id, amount: 100 }, Event::PoolExpiryBlockModified { pool_id, new_expiry_block: 60 }, Event::PoolRewardRateModified { pool_id, new_reward_rate_per_block: 150 }, - Event::RewardsHarvested { staker: staker2, pool_id, amount: 1433 } + Event::RewardsHarvested { caller: staker2, staker: staker2, pool_id, amount: 1433 } ] ); }); From 3035d6a507c99fee20aa4c837d735ed1ab6c8158 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Tue, 17 Sep 2024 12:01:12 +0000 Subject: [PATCH 150/159] ".git/.scripts/commands/bench-all/bench-all.sh" --pallet=pallet_asset_rewards --- .../src/weights/pallet_asset_rewards.rs | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs index 184babb8686f..8c546ecc1169 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_asset_rewards` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-09-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-09-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `runner-obbyq9g6-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 @@ -64,8 +64,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `358` // Estimated: `6360` - // Minimum execution time: 60_981_000 picoseconds. - Weight::from_parts(62_812_000, 0) + // Minimum execution time: 59_228_000 picoseconds. + Weight::from_parts(60_640_000, 0) .saturating_add(Weight::from_parts(0, 6360)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(5)) @@ -84,8 +84,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `872` // Estimated: `4809` - // Minimum execution time: 55_988_000 picoseconds. - Weight::from_parts(56_817_000, 0) + // Minimum execution time: 55_079_000 picoseconds. + Weight::from_parts(56_396_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -104,8 +104,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `872` // Estimated: `4809` - // Minimum execution time: 57_003_000 picoseconds. - Weight::from_parts(58_191_000, 0) + // Minimum execution time: 56_585_000 picoseconds. + Weight::from_parts(58_067_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -124,8 +124,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `1072` // Estimated: `6208` - // Minimum execution time: 78_620_000 picoseconds. - Weight::from_parts(80_355_000, 0) + // Minimum execution time: 77_177_000 picoseconds. + Weight::from_parts(79_034_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -136,8 +136,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `318` // Estimated: `4809` - // Minimum execution time: 16_823_000 picoseconds. - Weight::from_parts(17_233_000, 0) + // Minimum execution time: 16_339_000 picoseconds. + Weight::from_parts(16_853_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -148,8 +148,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `318` // Estimated: `4809` - // Minimum execution time: 16_067_000 picoseconds. - Weight::from_parts(17_025_000, 0) + // Minimum execution time: 16_282_000 picoseconds. + Weight::from_parts(16_663_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -160,8 +160,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `318` // Estimated: `4809` - // Minimum execution time: 17_472_000 picoseconds. - Weight::from_parts(18_036_000, 0) + // Minimum execution time: 17_137_000 picoseconds. + Weight::from_parts(17_608_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -180,8 +180,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `747` // Estimated: `6208` - // Minimum execution time: 62_101_000 picoseconds. - Weight::from_parts(63_647_000, 0) + // Minimum execution time: 60_634_000 picoseconds. + Weight::from_parts(62_132_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -208,8 +208,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `1105` // Estimated: `6208` - // Minimum execution time: 121_326_000 picoseconds. - Weight::from_parts(124_201_000, 0) + // Minimum execution time: 118_514_000 picoseconds. + Weight::from_parts(121_075_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(10)) From 1fb27c421ad821cf9cb86443eef0a9ca4c5ce653 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Tue, 17 Sep 2024 12:15:26 +0000 Subject: [PATCH 151/159] ".git/.scripts/commands/bench-all/bench-all.sh" --pallet=pallet_asset_rewards --- .../src/weights/pallet_asset_rewards.rs | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs index ee52ba6e7074..8da0f2980e84 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_asset_rewards` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-09-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-09-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `runner-obbyq9g6-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 @@ -64,8 +64,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `392` // Estimated: `6360` - // Minimum execution time: 60_753_000 picoseconds. - Weight::from_parts(61_702_000, 0) + // Minimum execution time: 59_601_000 picoseconds. + Weight::from_parts(60_370_000, 0) .saturating_add(Weight::from_parts(0, 6360)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(5)) @@ -84,8 +84,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `906` // Estimated: `4809` - // Minimum execution time: 52_703_000 picoseconds. - Weight::from_parts(53_986_000, 0) + // Minimum execution time: 52_160_000 picoseconds. + Weight::from_parts(54_104_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -104,8 +104,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `906` // Estimated: `4809` - // Minimum execution time: 54_053_000 picoseconds. - Weight::from_parts(54_983_000, 0) + // Minimum execution time: 54_962_000 picoseconds. + Weight::from_parts(56_052_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -124,8 +124,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `1106` // Estimated: `6208` - // Minimum execution time: 79_306_000 picoseconds. - Weight::from_parts(81_088_000, 0) + // Minimum execution time: 77_953_000 picoseconds. + Weight::from_parts(81_505_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -136,8 +136,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `318` // Estimated: `4809` - // Minimum execution time: 17_439_000 picoseconds. - Weight::from_parts(18_179_000, 0) + // Minimum execution time: 17_488_000 picoseconds. + Weight::from_parts(18_146_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -148,8 +148,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `318` // Estimated: `4809` - // Minimum execution time: 15_893_000 picoseconds. - Weight::from_parts(16_410_000, 0) + // Minimum execution time: 16_295_000 picoseconds. + Weight::from_parts(16_498_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -160,8 +160,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `318` // Estimated: `4809` - // Minimum execution time: 18_559_000 picoseconds. - Weight::from_parts(19_170_000, 0) + // Minimum execution time: 18_732_000 picoseconds. + Weight::from_parts(19_109_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -180,8 +180,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `781` // Estimated: `6208` - // Minimum execution time: 62_407_000 picoseconds. - Weight::from_parts(63_858_000, 0) + // Minimum execution time: 61_974_000 picoseconds. + Weight::from_parts(63_171_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -208,8 +208,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `1139` // Estimated: `6208` - // Minimum execution time: 120_522_000 picoseconds. - Weight::from_parts(123_335_000, 0) + // Minimum execution time: 118_767_000 picoseconds. + Weight::from_parts(121_162_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(10)) From ecac4b5599f2dbdd28862b289b69b3dacc846fbb Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Tue, 17 Sep 2024 12:56:10 +0000 Subject: [PATCH 152/159] ".git/.scripts/commands/bench-all/bench-all.sh" --pallet=pallet_asset_rewards --- substrate/frame/asset-rewards/src/weights.rs | 226 +++++++++++-------- 1 file changed, 131 insertions(+), 95 deletions(-) diff --git a/substrate/frame/asset-rewards/src/weights.rs b/substrate/frame/asset-rewards/src/weights.rs index 575bf97d0641..56166b071557 100644 --- a/substrate/frame/asset-rewards/src/weights.rs +++ b/substrate/frame/asset-rewards/src/weights.rs @@ -18,23 +18,25 @@ //! Autogenerated weights for `pallet_asset_rewards` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-07-31, STEPS: `50`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-09-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `cob`, CPU: `` +//! HOSTNAME: `runner-obbyq9g6-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/debug/substrate-node +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 -// --repeat=2 -// --pallet=pallet-asset-rewards +// --repeat=20 // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/asset-rewards/src/._weights0.rs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_asset_rewards +// --chain=dev +// --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/asset-rewards/src/weights.rs // --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] @@ -68,43 +70,41 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolCost` (r:0 w:1) /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::Pools` (r:0 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) fn create_pool() -> Weight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `6360` - // Minimum execution time: 708_000_000 picoseconds. - Weight::from_parts(779_000_000, 6360) + // Minimum execution time: 59_727_000 picoseconds. + Weight::from_parts(61_321_000, 6360) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:1 w:0) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) /// Storage: `AssetsFreezer::Freezes` (r:1 w:1) /// Proof: `AssetsFreezer::Freezes` (`max_values`: None, `max_size`: Some(105), added: 2580, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:0) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:1) /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn stake() -> Weight { // Proof Size summary in bytes: - // Measured: `852` - // Estimated: `3675` - // Minimum execution time: 441_000_000 picoseconds. - Weight::from_parts(460_000_000, 3675) - .saturating_add(T::DbWeight::get().reads(6_u64)) + // Measured: `935` + // Estimated: `3615` + // Minimum execution time: 54_405_000 picoseconds. + Weight::from_parts(56_192_000, 3615) + .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) /// Storage: `AssetsFreezer::Freezes` (r:1 w:1) @@ -115,15 +115,15 @@ impl WeightInfo for SubstrateWeight { /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn unstake() -> Weight { // Proof Size summary in bytes: - // Measured: `904` - // Estimated: `3599` - // Minimum execution time: 480_000_000 picoseconds. - Weight::from_parts(488_000_000, 3599) + // Measured: `935` + // Estimated: `3615` + // Minimum execution time: 57_507_000 picoseconds. + Weight::from_parts(58_775_000, 3615) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) /// Storage: `Assets::Asset` (r:1 w:1) @@ -132,48 +132,48 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn harvest_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `990` + // Measured: `1021` // Estimated: `6208` - // Minimum execution time: 659_000_000 picoseconds. - Weight::from_parts(660_000_000, 6208) + // Minimum execution time: 70_798_000 picoseconds. + Weight::from_parts(72_329_000, 6208) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) fn set_pool_reward_rate_per_block() -> Weight { // Proof Size summary in bytes: - // Measured: `316` - // Estimated: `3584` - // Minimum execution time: 121_000_000 picoseconds. - Weight::from_parts(125_000_000, 3584) + // Measured: `347` + // Estimated: `3615` + // Minimum execution time: 16_484_000 picoseconds. + Weight::from_parts(17_163_000, 3615) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) fn set_pool_admin() -> Weight { // Proof Size summary in bytes: - // Measured: `316` - // Estimated: `3584` - // Minimum execution time: 118_000_000 picoseconds. - Weight::from_parts(149_000_000, 3584) + // Measured: `347` + // Estimated: `3615` + // Minimum execution time: 14_708_000 picoseconds. + Weight::from_parts(15_268_000, 3615) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) fn set_pool_expiry_block() -> Weight { // Proof Size summary in bytes: - // Measured: `316` - // Estimated: `3584` - // Minimum execution time: 124_000_000 picoseconds. - Weight::from_parts(133_000_000, 3584) + // Measured: `347` + // Estimated: `3615` + // Minimum execution time: 17_389_000 picoseconds. + Weight::from_parts(17_838_000, 3615) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) /// Storage: `Assets::Asset` (r:1 w:1) /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `Assets::Account` (r:2 w:2) @@ -182,16 +182,35 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn deposit_reward_tokens() -> Weight { // Proof Size summary in bytes: - // Measured: `809` + // Measured: `840` // Estimated: `6208` - // Minimum execution time: 578_000_000 picoseconds. - Weight::from_parts(578_000_000, 6208) + // Minimum execution time: 58_792_000 picoseconds. + Weight::from_parts(60_360_000, 6208) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - // TODO: replace with actual weight. + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:0) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::PoolCost` (r:1 w:1) + /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `MaxEncodedLen`) fn cleanup_pool() -> Weight { - Weight::MAX + // Proof Size summary in bytes: + // Measured: `1236` + // Estimated: `6208` + // Minimum execution time: 110_448_000 picoseconds. + Weight::from_parts(112_767_000, 6208) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) } } @@ -204,43 +223,41 @@ impl WeightInfo for () { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(211), added: 2686, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolCost` (r:0 w:1) /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::Pools` (r:0 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) fn create_pool() -> Weight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `6360` - // Minimum execution time: 708_000_000 picoseconds. - Weight::from_parts(779_000_000, 6360) + // Minimum execution time: 59_727_000 picoseconds. + Weight::from_parts(61_321_000, 6360) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:1 w:0) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:1 w:0) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) /// Storage: `AssetsFreezer::Freezes` (r:1 w:1) /// Proof: `AssetsFreezer::Freezes` (`max_values`: None, `max_size`: Some(105), added: 2580, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:1 w:0) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) /// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:1) /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn stake() -> Weight { // Proof Size summary in bytes: - // Measured: `852` - // Estimated: `3675` - // Minimum execution time: 441_000_000 picoseconds. - Weight::from_parts(460_000_000, 3675) - .saturating_add(RocksDbWeight::get().reads(6_u64)) + // Measured: `935` + // Estimated: `3615` + // Minimum execution time: 54_405_000 picoseconds. + Weight::from_parts(56_192_000, 3615) + .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) /// Storage: `AssetsFreezer::Freezes` (r:1 w:1) @@ -251,15 +268,15 @@ impl WeightInfo for () { /// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn unstake() -> Weight { // Proof Size summary in bytes: - // Measured: `904` - // Estimated: `3599` - // Minimum execution time: 480_000_000 picoseconds. - Weight::from_parts(488_000_000, 3599) + // Measured: `935` + // Estimated: `3615` + // Minimum execution time: 57_507_000 picoseconds. + Weight::from_parts(58_775_000, 3615) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolStakers` (r:1 w:1) /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) /// Storage: `Assets::Asset` (r:1 w:1) @@ -268,48 +285,48 @@ impl WeightInfo for () { /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) fn harvest_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `990` + // Measured: `1021` // Estimated: `6208` - // Minimum execution time: 659_000_000 picoseconds. - Weight::from_parts(660_000_000, 6208) + // Minimum execution time: 70_798_000 picoseconds. + Weight::from_parts(72_329_000, 6208) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) fn set_pool_reward_rate_per_block() -> Weight { // Proof Size summary in bytes: - // Measured: `316` - // Estimated: `3584` - // Minimum execution time: 121_000_000 picoseconds. - Weight::from_parts(125_000_000, 3584) + // Measured: `347` + // Estimated: `3615` + // Minimum execution time: 16_484_000 picoseconds. + Weight::from_parts(17_163_000, 3615) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) fn set_pool_admin() -> Weight { // Proof Size summary in bytes: - // Measured: `316` - // Estimated: `3584` - // Minimum execution time: 118_000_000 picoseconds. - Weight::from_parts(149_000_000, 3584) + // Measured: `347` + // Estimated: `3615` + // Minimum execution time: 14_708_000 picoseconds. + Weight::from_parts(15_268_000, 3615) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:1) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) fn set_pool_expiry_block() -> Weight { // Proof Size summary in bytes: - // Measured: `316` - // Estimated: `3584` - // Minimum execution time: 124_000_000 picoseconds. - Weight::from_parts(133_000_000, 3584) + // Measured: `347` + // Estimated: `3615` + // Minimum execution time: 17_389_000 picoseconds. + Weight::from_parts(17_838_000, 3615) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `AssetRewards::Pools` (r:1 w:0) - /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(119), added: 2594, mode: `MaxEncodedLen`) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) /// Storage: `Assets::Asset` (r:1 w:1) /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) /// Storage: `Assets::Account` (r:2 w:2) @@ -318,15 +335,34 @@ impl WeightInfo for () { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) fn deposit_reward_tokens() -> Weight { // Proof Size summary in bytes: - // Measured: `809` + // Measured: `840` // Estimated: `6208` - // Minimum execution time: 578_000_000 picoseconds. - Weight::from_parts(578_000_000, 6208) + // Minimum execution time: 58_792_000 picoseconds. + Weight::from_parts(60_360_000, 6208) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - // TODO: replace with actual weight. + /// Storage: `AssetRewards::Pools` (r:1 w:1) + /// Proof: `AssetRewards::Pools` (`max_values`: None, `max_size`: Some(150), added: 2625, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::PoolStakers` (r:1 w:0) + /// Proof: `AssetRewards::PoolStakers` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `AssetRewards::PoolCost` (r:1 w:1) + /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `MaxEncodedLen`) fn cleanup_pool() -> Weight { - Weight::MAX + // Proof Size summary in bytes: + // Measured: `1236` + // Estimated: `6208` + // Minimum execution time: 110_448_000 picoseconds. + Weight::from_parts(112_767_000, 6208) + .saturating_add(RocksDbWeight::get().reads(9_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) } } From 7ffe9d158090fcf37c924031b1a7c56dc3aef5fc Mon Sep 17 00:00:00 2001 From: muharem Date: Sun, 22 Dec 2024 16:50:55 +0100 Subject: [PATCH 153/159] fmt --- cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs | 3 ++- .../parachains/runtimes/assets/asset-hub-westend/src/lib.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 026e3ca733a2..78c09f7ac9e9 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -606,7 +606,8 @@ impl InstanceFilter for ProxyType { RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } | RuntimeCall::NftFractionalization { .. } | - RuntimeCall::Nfts { .. } | RuntimeCall::Uniques { .. } + RuntimeCall::Nfts { .. } | + RuntimeCall::Uniques { .. } ) }, ProxyType::AssetOwner => matches!( 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 9376f43faf1c..36ab3fb01cec 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -655,7 +655,8 @@ impl InstanceFilter for ProxyType { RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } | RuntimeCall::NftFractionalization { .. } | - RuntimeCall::Nfts { .. } | RuntimeCall::Uniques { .. } + RuntimeCall::Nfts { .. } | + RuntimeCall::Uniques { .. } ) }, ProxyType::AssetOwner => matches!( From 8b85949035ffb579631e61a6180a5d1e7fac9962 Mon Sep 17 00:00:00 2001 From: muharem Date: Mon, 23 Dec 2024 09:28:14 +0100 Subject: [PATCH 154/159] add missing config type --- substrate/frame/asset-rewards/src/mock.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/substrate/frame/asset-rewards/src/mock.rs b/substrate/frame/asset-rewards/src/mock.rs index 57480c4c4cba..87c8a8a0dea0 100644 --- a/substrate/frame/asset-rewards/src/mock.rs +++ b/substrate/frame/asset-rewards/src/mock.rs @@ -71,6 +71,7 @@ impl pallet_balances::Config for MockRuntime { type MaxFreezes = ConstU32<50>; type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; + type DoneSlashHandler = (); } impl pallet_assets::Config for MockRuntime { From e21ae76588df2e6db255e2f63c59d87af0d8bd95 Mon Sep 17 00:00:00 2001 From: muharem Date: Tue, 14 Jan 2025 13:59:57 +0800 Subject: [PATCH 155/159] fix tests --- .../emulated/tests/assets/asset-hub-rococo/src/lib.rs | 2 +- .../tests/assets/asset-hub-rococo/src/tests/reward_pool.rs | 2 ++ .../emulated/tests/assets/asset-hub-westend/src/lib.rs | 1 + .../tests/assets/asset-hub-westend/src/tests/reward_pool.rs | 2 ++ 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs index ca067822f29e..513ca278a319 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs @@ -80,7 +80,7 @@ mod imports { xcm_config::{ UniversalLocation as RococoUniversalLocation, XcmConfig as RococoXcmConfig, }, - OriginCaller as RococoOriginCaller, + Dmp, OriginCaller as RococoOriginCaller, }, RococoRelayPallet as RococoPallet, }, diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reward_pool.rs index 20ba6d36f327..2f3ee536a7b9 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reward_pool.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reward_pool.rs @@ -51,6 +51,8 @@ fn treasury_creates_asset_reward_pool() { type RococoRuntimeEvent = ::RuntimeEvent; type RococoRuntimeOrigin = ::RuntimeOrigin; + Dmp::make_parachain_reachable(AssetHubRococo::para_id()); + let staked_asset_id = bx!(RelayLocation::get()); let reward_asset_id = bx!(RelayLocation::get()); diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs index 06c0e639b1f1..68dc87250f76 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs @@ -84,6 +84,7 @@ mod imports { xcm_config::{ UniversalLocation as WestendUniversalLocation, XcmConfig as WestendXcmConfig, }, + Dmp, }, WestendRelayPallet as WestendPallet, }, diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reward_pool.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reward_pool.rs index fea5a8954cf9..4df51abcaceb 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reward_pool.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reward_pool.rs @@ -50,6 +50,8 @@ fn treasury_creates_asset_reward_pool() { type WestendRuntimeEvent = ::RuntimeEvent; type WestendRuntimeOrigin = ::RuntimeOrigin; + Dmp::make_parachain_reachable(AssetHubWestend::para_id()); + let staked_asset_id = bx!(RelayLocation::get()); let reward_asset_id = bx!(RelayLocation::get()); From bca554459fd82e531f99de6a1dbf19f15e1ccad7 Mon Sep 17 00:00:00 2001 From: muharem Date: Tue, 14 Jan 2025 14:07:26 +0800 Subject: [PATCH 156/159] update pr doc --- prdoc/pr_3926.prdoc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/prdoc/pr_3926.prdoc b/prdoc/pr_3926.prdoc index b8992866c398..7f352f7a45fb 100644 --- a/prdoc/pr_3926.prdoc +++ b/prdoc/pr_3926.prdoc @@ -11,7 +11,7 @@ crates: - name: pallet-asset-rewards bump: major - name: polkadot-sdk - bump: patch + bump: minor - name: kitchensink-runtime bump: major - name: asset-hub-rococo-runtime @@ -19,8 +19,12 @@ crates: - name: asset-hub-westend-runtime bump: major - name: assets-common - bump: patch + bump: minor - name: rococo-runtime - bump: patch + bump: minor - name: westend-runtime bump: patch + - name: frame-support + bump: minor + - name: emulated-integration-tests-common + bump: minor From c9eb60954d1b39f3bbe4822a6e6b7abe042f0591 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Tue, 14 Jan 2025 07:32:09 +0000 Subject: [PATCH 157/159] ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=asset-hub-westend --runtime_dir=assets --target_dir=cumulus --pallet=pallet_asset_rewards --- .../src/weights/pallet_asset_rewards.rs | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs index 8da0f2980e84..3bbc289fec7b 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_asset_rewards.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_asset_rewards` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-09-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-01-14, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-obbyq9g6-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -55,7 +55,7 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolCost` (r:0 w:1) /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::Pools` (r:0 w:1) @@ -64,8 +64,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `392` // Estimated: `6360` - // Minimum execution time: 59_601_000 picoseconds. - Weight::from_parts(60_370_000, 0) + // Minimum execution time: 60_734_000 picoseconds. + Weight::from_parts(61_828_000, 0) .saturating_add(Weight::from_parts(0, 6360)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(5)) @@ -84,8 +84,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `906` // Estimated: `4809` - // Minimum execution time: 52_160_000 picoseconds. - Weight::from_parts(54_104_000, 0) + // Minimum execution time: 56_014_000 picoseconds. + Weight::from_parts(58_487_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -104,8 +104,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `906` // Estimated: `4809` - // Minimum execution time: 54_962_000 picoseconds. - Weight::from_parts(56_052_000, 0) + // Minimum execution time: 59_071_000 picoseconds. + Weight::from_parts(60_631_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -124,8 +124,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `1106` // Estimated: `6208` - // Minimum execution time: 77_953_000 picoseconds. - Weight::from_parts(81_505_000, 0) + // Minimum execution time: 80_585_000 picoseconds. + Weight::from_parts(82_186_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -136,8 +136,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `318` // Estimated: `4809` - // Minimum execution time: 17_488_000 picoseconds. - Weight::from_parts(18_146_000, 0) + // Minimum execution time: 17_083_000 picoseconds. + Weight::from_parts(17_816_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -148,8 +148,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `318` // Estimated: `4809` - // Minimum execution time: 16_295_000 picoseconds. - Weight::from_parts(16_498_000, 0) + // Minimum execution time: 15_269_000 picoseconds. + Weight::from_parts(15_881_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -160,8 +160,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `318` // Estimated: `4809` - // Minimum execution time: 18_732_000 picoseconds. - Weight::from_parts(19_109_000, 0) + // Minimum execution time: 17_482_000 picoseconds. + Weight::from_parts(18_124_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -180,8 +180,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `781` // Estimated: `6208` - // Minimum execution time: 61_974_000 picoseconds. - Weight::from_parts(63_171_000, 0) + // Minimum execution time: 66_644_000 picoseconds. + Weight::from_parts(67_950_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -201,15 +201,15 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo /// Storage: `AssetRewards::PoolCost` (r:1 w:1) /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(103), added: 2578, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(157), added: 2632, mode: `MaxEncodedLen`) /// Storage: `AssetsFreezer::Freezes` (r:0 w:1) /// Proof: `AssetsFreezer::Freezes` (`max_values`: None, `max_size`: Some(87), added: 2562, mode: `MaxEncodedLen`) fn cleanup_pool() -> Weight { // Proof Size summary in bytes: // Measured: `1139` // Estimated: `6208` - // Minimum execution time: 118_767_000 picoseconds. - Weight::from_parts(121_162_000, 0) + // Minimum execution time: 124_136_000 picoseconds. + Weight::from_parts(128_642_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(10)) From 7a1e11325e8356ddffee7aa4c0fdb07e95b056c6 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Tue, 14 Jan 2025 07:33:31 +0000 Subject: [PATCH 158/159] ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=asset-hub-rococo --runtime_dir=assets --target_dir=cumulus --pallet=pallet_asset_rewards --- .../src/weights/pallet_asset_rewards.rs | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs index 8c546ecc1169..218c93c51035 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_asset_rewards.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_asset_rewards` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-09-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-01-14, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-obbyq9g6-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -64,8 +64,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `358` // Estimated: `6360` - // Minimum execution time: 59_228_000 picoseconds. - Weight::from_parts(60_640_000, 0) + // Minimum execution time: 65_882_000 picoseconds. + Weight::from_parts(67_073_000, 0) .saturating_add(Weight::from_parts(0, 6360)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(5)) @@ -84,8 +84,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `872` // Estimated: `4809` - // Minimum execution time: 55_079_000 picoseconds. - Weight::from_parts(56_396_000, 0) + // Minimum execution time: 56_950_000 picoseconds. + Weight::from_parts(58_088_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -104,8 +104,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `872` // Estimated: `4809` - // Minimum execution time: 56_585_000 picoseconds. - Weight::from_parts(58_067_000, 0) + // Minimum execution time: 59_509_000 picoseconds. + Weight::from_parts(61_064_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -124,8 +124,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `1072` // Estimated: `6208` - // Minimum execution time: 77_177_000 picoseconds. - Weight::from_parts(79_034_000, 0) + // Minimum execution time: 80_685_000 picoseconds. + Weight::from_parts(83_505_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -136,8 +136,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `318` // Estimated: `4809` - // Minimum execution time: 16_339_000 picoseconds. - Weight::from_parts(16_853_000, 0) + // Minimum execution time: 17_032_000 picoseconds. + Weight::from_parts(17_628_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -148,8 +148,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `318` // Estimated: `4809` - // Minimum execution time: 16_282_000 picoseconds. - Weight::from_parts(16_663_000, 0) + // Minimum execution time: 15_290_000 picoseconds. + Weight::from_parts(16_212_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -160,8 +160,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `318` // Estimated: `4809` - // Minimum execution time: 17_137_000 picoseconds. - Weight::from_parts(17_608_000, 0) + // Minimum execution time: 17_721_000 picoseconds. + Weight::from_parts(18_603_000, 0) .saturating_add(Weight::from_parts(0, 4809)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -180,8 +180,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `747` // Estimated: `6208` - // Minimum execution time: 60_634_000 picoseconds. - Weight::from_parts(62_132_000, 0) + // Minimum execution time: 67_754_000 picoseconds. + Weight::from_parts(69_428_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) @@ -208,8 +208,8 @@ impl pallet_asset_rewards::WeightInfo for WeightInfo // Proof Size summary in bytes: // Measured: `1105` // Estimated: `6208` - // Minimum execution time: 118_514_000 picoseconds. - Weight::from_parts(121_075_000, 0) + // Minimum execution time: 127_524_000 picoseconds. + Weight::from_parts(130_238_000, 0) .saturating_add(Weight::from_parts(0, 6208)) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(10)) From 7e9cb27d000d6c3927e2ee097a51514351a65267 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Tue, 14 Jan 2025 14:54:22 +0000 Subject: [PATCH 159/159] ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=dev --target_dir=substrate --features=runtime-benchmarks --pallet=pallet_asset_rewards --- substrate/frame/asset-rewards/src/weights.rs | 84 ++++++++++---------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/substrate/frame/asset-rewards/src/weights.rs b/substrate/frame/asset-rewards/src/weights.rs index 56166b071557..c9e2d0fd251a 100644 --- a/substrate/frame/asset-rewards/src/weights.rs +++ b/substrate/frame/asset-rewards/src/weights.rs @@ -18,9 +18,9 @@ //! Autogenerated weights for `pallet_asset_rewards` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-09-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-01-14, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-obbyq9g6-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-ys-ssygq-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: @@ -70,7 +70,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(373), added: 2848, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolCost` (r:0 w:1) /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::Pools` (r:0 w:1) @@ -79,8 +79,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `495` // Estimated: `6360` - // Minimum execution time: 59_727_000 picoseconds. - Weight::from_parts(61_321_000, 6360) + // Minimum execution time: 62_655_000 picoseconds. + Weight::from_parts(63_723_000, 6360) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -98,8 +98,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `935` // Estimated: `3615` - // Minimum execution time: 54_405_000 picoseconds. - Weight::from_parts(56_192_000, 3615) + // Minimum execution time: 54_463_000 picoseconds. + Weight::from_parts(55_974_000, 3615) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -117,8 +117,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `935` // Estimated: `3615` - // Minimum execution time: 57_507_000 picoseconds. - Weight::from_parts(58_775_000, 3615) + // Minimum execution time: 55_749_000 picoseconds. + Weight::from_parts(57_652_000, 3615) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -134,8 +134,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1021` // Estimated: `6208` - // Minimum execution time: 70_798_000 picoseconds. - Weight::from_parts(72_329_000, 6208) + // Minimum execution time: 69_372_000 picoseconds. + Weight::from_parts(70_278_000, 6208) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -145,8 +145,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `347` // Estimated: `3615` - // Minimum execution time: 16_484_000 picoseconds. - Weight::from_parts(17_163_000, 3615) + // Minimum execution time: 19_284_000 picoseconds. + Weight::from_parts(19_791_000, 3615) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -156,8 +156,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `347` // Estimated: `3615` - // Minimum execution time: 14_708_000 picoseconds. - Weight::from_parts(15_268_000, 3615) + // Minimum execution time: 17_388_000 picoseconds. + Weight::from_parts(18_390_000, 3615) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -167,8 +167,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `347` // Estimated: `3615` - // Minimum execution time: 17_389_000 picoseconds. - Weight::from_parts(17_838_000, 3615) + // Minimum execution time: 19_780_000 picoseconds. + Weight::from_parts(20_676_000, 3615) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -184,8 +184,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `840` // Estimated: `6208` - // Minimum execution time: 58_792_000 picoseconds. - Weight::from_parts(60_360_000, 6208) + // Minimum execution time: 57_746_000 picoseconds. + Weight::from_parts(59_669_000, 6208) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -202,13 +202,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: `AssetRewards::PoolCost` (r:1 w:1) /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(373), added: 2848, mode: `MaxEncodedLen`) fn cleanup_pool() -> Weight { // Proof Size summary in bytes: // Measured: `1236` // Estimated: `6208` - // Minimum execution time: 110_448_000 picoseconds. - Weight::from_parts(112_767_000, 6208) + // Minimum execution time: 110_443_000 picoseconds. + Weight::from_parts(113_149_000, 6208) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } @@ -223,7 +223,7 @@ impl WeightInfo for () { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(373), added: 2848, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::PoolCost` (r:0 w:1) /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `AssetRewards::Pools` (r:0 w:1) @@ -232,8 +232,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `495` // Estimated: `6360` - // Minimum execution time: 59_727_000 picoseconds. - Weight::from_parts(61_321_000, 6360) + // Minimum execution time: 62_655_000 picoseconds. + Weight::from_parts(63_723_000, 6360) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -251,8 +251,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `935` // Estimated: `3615` - // Minimum execution time: 54_405_000 picoseconds. - Weight::from_parts(56_192_000, 3615) + // Minimum execution time: 54_463_000 picoseconds. + Weight::from_parts(55_974_000, 3615) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -270,8 +270,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `935` // Estimated: `3615` - // Minimum execution time: 57_507_000 picoseconds. - Weight::from_parts(58_775_000, 3615) + // Minimum execution time: 55_749_000 picoseconds. + Weight::from_parts(57_652_000, 3615) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -287,8 +287,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1021` // Estimated: `6208` - // Minimum execution time: 70_798_000 picoseconds. - Weight::from_parts(72_329_000, 6208) + // Minimum execution time: 69_372_000 picoseconds. + Weight::from_parts(70_278_000, 6208) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -298,8 +298,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `347` // Estimated: `3615` - // Minimum execution time: 16_484_000 picoseconds. - Weight::from_parts(17_163_000, 3615) + // Minimum execution time: 19_284_000 picoseconds. + Weight::from_parts(19_791_000, 3615) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -309,8 +309,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `347` // Estimated: `3615` - // Minimum execution time: 14_708_000 picoseconds. - Weight::from_parts(15_268_000, 3615) + // Minimum execution time: 17_388_000 picoseconds. + Weight::from_parts(18_390_000, 3615) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -320,8 +320,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `347` // Estimated: `3615` - // Minimum execution time: 17_389_000 picoseconds. - Weight::from_parts(17_838_000, 3615) + // Minimum execution time: 19_780_000 picoseconds. + Weight::from_parts(20_676_000, 3615) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -337,8 +337,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `840` // Estimated: `6208` - // Minimum execution time: 58_792_000 picoseconds. - Weight::from_parts(60_360_000, 6208) + // Minimum execution time: 57_746_000 picoseconds. + Weight::from_parts(59_669_000, 6208) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -355,13 +355,13 @@ impl WeightInfo for () { /// Storage: `AssetRewards::PoolCost` (r:1 w:1) /// Proof: `AssetRewards::PoolCost` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `MaxEncodedLen`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(373), added: 2848, mode: `MaxEncodedLen`) fn cleanup_pool() -> Weight { // Proof Size summary in bytes: // Measured: `1236` // Estimated: `6208` - // Minimum execution time: 110_448_000 picoseconds. - Weight::from_parts(112_767_000, 6208) + // Minimum execution time: 110_443_000 picoseconds. + Weight::from_parts(113_149_000, 6208) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) }