difftreelog
Merge pull request #579 from UniqueNetwork/doc/app-promotion
in: master
added `doc` to app promotion
16 files changed
Cargo.lockdiffbeforeafterboth573357335734[[package]]5734[[package]]5735name = "pallet-evm-contract-helpers"5735name = "pallet-evm-contract-helpers"5736version = "0.2.0"5736version = "0.3.0"5737dependencies = [5737dependencies = [5738 "ethereum",5738 "ethereum",5739 "evm-coder",5739 "evm-coder",123161231612317[[package]]12317[[package]]12318name = "unique-rpc"12318name = "unique-rpc"12319version = "0.1.1"12319version = "0.1.2"12320dependencies = [12320dependencies = [12321 "app-promotion-rpc",12321 "app-promotion-rpc",12322 "fc-db",12322 "fc-db",node/cli/CHANGELOG.mddiffbeforeafterboth1<!-- bureaucrate goes here -->1<!-- bureaucrate goes here -->23## [v0.9.27] 2022-09-0845### Added6- Support RPC for `AppPromotion` pallet. 72## [v0.9.27] 2022-08-168## [v0.9.27] 2022-08-16394### Other changes10### Other changesnode/rpc/CHANGELOG.mddiffbeforeafterboth1<!-- bureaucrate goes here -->1<!-- bureaucrate goes here -->2## [v0.1.2] 2022-09-0834### Added5- Support RPC for `AppPromotion` pallet. 62## [v0.1.1] 2022-08-167## [v0.1.1] 2022-08-16384### Other changes9### Other changesnode/rpc/Cargo.tomldiffbeforeafterboth1[package]1[package]2name = "unique-rpc"2name = "unique-rpc"3version = "0.1.1"3version = "0.1.2"4authors = ['Unique Network <support@uniquenetwork.io>']4authors = ['Unique Network <support@uniquenetwork.io>']5license = 'GPLv3'5license = 'GPLv3'6edition = "2021"6edition = "2021"pallets/app-promotion/src/benchmarking.rsdiffbeforeafterboth112 let share = Perbill::from_rational(1u32, 20);112 let share = Perbill::from_rational(1u32, 20);113 let _ = <T as Config>::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());113 let _ = <T as Config>::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());114 (0..10).map(|_| {114 (0..10).map(|_| {115 // used to change block number115 <frame_system::Pallet<T>>::finalize();116 <frame_system::Pallet<T>>::finalize();116 PromototionPallet::<T>::stake(RawOrigin::Signed(caller.clone()).into(), share * <T as Config>::Currency::total_balance(&caller))117 PromototionPallet::<T>::stake(RawOrigin::Signed(caller.clone()).into(), share * <T as Config>::Currency::total_balance(&caller))117 }).collect::<Result<Vec<_>, _>>()?;118 }).collect::<Result<Vec<_>, _>>()?;pallets/app-promotion/src/lib.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617//! # App promotion17//! # App Promotion pallet18//!18//!19//! The app promotion pallet is designed to ... .19//! The pallet implements the mechanics of staking and sponsoring collections/contracts.20//!21//! - [`Config`]22//! - [`Pallet`]23//! - [`Error`]24//! - [`Event`]25//!26//! ## Overview27//! The App Promotion pallet allows fund holders to stake at a certain daily rate of return.28//! The mechanics implemented in the pallet allow it to act as a sponsor for collections / contracts,29//! the list of which is set by the pallet administrator.30//! 20//!31//!21//! ## Interface32//! ## Interface33//! The pallet provides interfaces for funds, collection/contract operations (see [types] module).3422//!35//!23//! ### Dispatchable Functions36//! ### Dispatchable Functions37//! - [`set_admin_address`][`Pallet::set_admin_address`] - sets an address as the the admin.38//! - [`stake`][`Pallet::stake`] - stakes the amount of native tokens.39//! - [`unstake`][`Pallet::unstake`] - unstakes all stakes.40//! - [`sponsor_collection`][`Pallet::sponsor_collection`] - sets the pallet to be the sponsor for the collection.41//! - [`stop_sponsoring_collection`][`Pallet::stop_sponsoring_collection`] - removes the pallet as the sponsor for the collection.42//! - [`sponsor_contract`][`Pallet::sponsor_contract`] - sets the pallet to be the sponsor for the contract.43//! - [`stop_sponsoring_contract`][`Pallet::stop_sponsoring_contract`] - removes the pallet as the sponsor for the contract.44//! - [`payout_stakers`][`Pallet::payout_stakers`] - recalculates interest for the specified number of stakers.24//!45//!254626// #![recursion_limit = "1024"]47// #![recursion_limit = "1024"]95 /// Type for interacting with conrtacts116 /// Type for interacting with conrtacts96 type ContractHandler: ContractHandler<AccountId = Self::CrossAccountId, ContractId = H160>;117 type ContractHandler: ContractHandler<AccountId = Self::CrossAccountId, ContractId = H160>;9711898 /// ID for treasury119 /// `AccountId` for treasury99 type TreasuryAccountId: Get<Self::AccountId>;120 type TreasuryAccountId: Get<Self::AccountId>;100121101 /// The app's pallet id, used for deriving its sovereign account ID.122 /// The app's pallet id, used for deriving its sovereign account address.102 #[pallet::constant]123 #[pallet::constant]103 type PalletId: Get<PalletId>;124 type PalletId: Get<PalletId>;104125138 /// Staking recalculation was performed159 /// Staking recalculation was performed139 ///160 ///140 /// # Arguments161 /// # Arguments141 /// * AccountId: ID of the staker.162 /// * AccountId: account of the staker.142 /// * Balance : recalculation base163 /// * Balance : recalculation base143 /// * Balance : total income164 /// * Balance : total income144 StakingRecalculation(165 StakingRecalculation(153 /// Staking was performed174 /// Staking was performed154 ///175 ///155 /// # Arguments176 /// # Arguments156 /// * AccountId: ID of the staker177 /// * AccountId: account of the staker157 /// * Balance : staking amount178 /// * Balance : staking amount158 Stake(T::AccountId, BalanceOf<T>),179 Stake(T::AccountId, BalanceOf<T>),159180160 /// Unstaking was performed181 /// Unstaking was performed161 ///182 ///162 /// # Arguments183 /// # Arguments163 /// * AccountId: ID of the staker184 /// * AccountId: account of the staker164 /// * Balance : unstaking amount185 /// * Balance : unstaking amount165 Unstake(T::AccountId, BalanceOf<T>),186 Unstake(T::AccountId, BalanceOf<T>),166187167 /// The admin was set188 /// The admin was set168 ///189 ///169 /// # Arguments190 /// # Arguments170 /// * AccountId: ID of the admin191 /// * AccountId: account address of the admin171 SetAdmin(T::AccountId),192 SetAdmin(T::AccountId),172 }193 }173194187 IncorrectLockedBalanceOperation,208 IncorrectLockedBalanceOperation,188 }209 }189210211 /// Stores the total staked amount.190 #[pallet::storage]212 #[pallet::storage]191 pub type TotalStaked<T: Config> = StorageValue<Value = BalanceOf<T>, QueryKind = ValueQuery>;213 pub type TotalStaked<T: Config> = StorageValue<Value = BalanceOf<T>, QueryKind = ValueQuery>;192214215 /// Stores the `admin` account. Some extrinsics can only be executed if they were signed by `admin`.193 #[pallet::storage]216 #[pallet::storage]194 pub type Admin<T: Config> = StorageValue<Value = T::AccountId, QueryKind = OptionQuery>;217 pub type Admin<T: Config> = StorageValue<Value = T::AccountId, QueryKind = OptionQuery>;195218196 /// Amount of tokens staked by account in the blocknumber.219 /// Stores the amount of tokens staked by account in the blocknumber.220 ///221 /// * **Key1** - Staker account.222 /// * **Key2** - Relay block number when the stake was made.223 /// * **(Balance, BlockNumber)** - Balance of the stake.224 /// The number of the relay block in which we must perform the interest recalculation197 #[pallet::storage]225 #[pallet::storage]198 pub type Staked<T: Config> = StorageNMap<226 pub type Staked<T: Config> = StorageNMap<199 Key = (227 Key = (204 QueryKind = ValueQuery,232 QueryKind = ValueQuery,205 >;233 >;234206 /// Amount of stakes for an Account235 /// Stores amount of stakes for an `Account`.236 ///237 /// * **Key** - Staker account.238 /// * **Value** - Amount of stakes.207 #[pallet::storage]239 #[pallet::storage]208 pub type StakesPerAccount<T: Config> =240 pub type StakesPerAccount<T: Config> =209 StorageMap<_, Blake2_128Concat, T::AccountId, u8, ValueQuery>;241 StorageMap<_, Blake2_128Concat, T::AccountId, u8, ValueQuery>;210242243 /// Stores amount of stakes for an `Account`.244 ///245 /// * **Key** - Staker account.246 /// * **Value** - Amount of stakes.211 #[pallet::storage]247 #[pallet::storage]212 pub type PendingUnstake<T: Config> = StorageMap<248 pub type PendingUnstake<T: Config> = StorageMap<213 _,249 _,252 T::BlockNumber: From<u32> + Into<u32>,288 T::BlockNumber: From<u32> + Into<u32>,253 <<T as Config>::Currency as Currency<T::AccountId>>::Balance: Sum + From<u128>,289 <<T as Config>::Currency as Currency<T::AccountId>>::Balance: Sum + From<u128>,254 {290 {291 /// Sets an address as the the admin.292 ///293 /// # Permissions294 ///295 /// * Sudo296 ///297 /// # Arguments298 ///299 /// * `admin`: account of the new admin.255 #[pallet::weight(T::WeightInfo::set_admin_address())]300 #[pallet::weight(T::WeightInfo::set_admin_address())]256 pub fn set_admin_address(origin: OriginFor<T>, admin: T::CrossAccountId) -> DispatchResult {301 pub fn set_admin_address(origin: OriginFor<T>, admin: T::CrossAccountId) -> DispatchResult {257 ensure_root(origin)?;302 ensure_root(origin)?;263 Ok(())308 Ok(())264 }309 }265310311 /// Stakes the amount of native tokens.312 /// Sets `amount` to the locked state.313 /// The maximum number of stakes for a staker is 10.314 ///315 /// # Arguments316 ///317 /// * `amount`: in native tokens.266 #[pallet::weight(T::WeightInfo::stake())]318 #[pallet::weight(T::WeightInfo::stake())]267 pub fn stake(staker: OriginFor<T>, amount: BalanceOf<T>) -> DispatchResult {319 pub fn stake(staker: OriginFor<T>, amount: BalanceOf<T>) -> DispatchResult {268 let staker_id = ensure_signed(staker)?;320 let staker_id = ensure_signed(staker)?;280 let balance =332 let balance =281 <<T as Config>::Currency as Currency<T::AccountId>>::free_balance(&staker_id);333 <<T as Config>::Currency as Currency<T::AccountId>>::free_balance(&staker_id);282334335 // checks that we can lock `amount` on the `staker` account.283 <<T as Config>::Currency as Currency<T::AccountId>>::ensure_can_withdraw(336 <<T as Config>::Currency as Currency<T::AccountId>>::ensure_can_withdraw(284 &staker_id,337 &staker_id,285 amount,338 amount,293346294 let block_number = T::RelayBlockNumberProvider::current_block_number();347 let block_number = T::RelayBlockNumberProvider::current_block_number();295348349 // Calculation of the number of recalculation periods,350 // after how much the first interest calculation should be performed for the stake296 let recalculate_after_interval: T::BlockNumber =351 let recalculate_after_interval: T::BlockNumber =297 if block_number % T::RecalculationInterval::get() == 0u32.into() {352 if block_number % T::RecalculationInterval::get() == 0u32.into() {298 1u32.into()353 1u32.into()299 } else {354 } else {300 2u32.into()355 2u32.into()301 };356 };302357358 // Сalculation of the number of the relay block359 // in which it is necessary to accrue remuneration for the stake.303 let recalc_block = (block_number / T::RecalculationInterval::get()360 let recalc_block = (block_number / T::RecalculationInterval::get()304 + recalculate_after_interval)361 + recalculate_after_interval)305 * T::RecalculationInterval::get();362 * T::RecalculationInterval::get();327 Ok(())384 Ok(())328 }385 }329386387 /// Unstakes all stakes.388 /// Moves the sum of all stakes to the `reserved` state.389 /// After the end of `PendingInterval` this sum becomes completely390 /// free for further use.330 #[pallet::weight(T::WeightInfo::unstake())]391 #[pallet::weight(T::WeightInfo::unstake())]331 pub fn unstake(staker: OriginFor<T>) -> DispatchResultWithPostInfo {392 pub fn unstake(staker: OriginFor<T>) -> DispatchResultWithPostInfo {332 let staker_id = ensure_signed(staker)?;393 let staker_id = ensure_signed(staker)?;394395 // calculate block number where the sum would be free333 let block = <frame_system::Pallet<T>>::block_number() + T::PendingInterval::get();396 let block = <frame_system::Pallet<T>>::block_number() + T::PendingInterval::get();397334 let mut pendings = <PendingUnstake<T>>::get(block);398 let mut pendings = <PendingUnstake<T>>::get(block);335399400 // checks that we can do unreserve stakes in the block336 ensure!(!pendings.is_full(), Error::<T>::PendingForBlockOverflow);401 ensure!(!pendings.is_full(), Error::<T>::PendingForBlockOverflow);337402338 let mut total_stakes = 0u64;403 let mut total_stakes = 0u64;371 Ok(None.into())436 Ok(None.into())372 }437 }373438439 /// Sets the pallet to be the sponsor for the collection.440 ///441 /// # Permissions442 ///443 /// * Pallet admin444 ///445 /// # Arguments446 ///447 /// * `collection_id`: ID of the collection that will be sponsored by `pallet_id`374 #[pallet::weight(T::WeightInfo::sponsor_collection())]448 #[pallet::weight(T::WeightInfo::sponsor_collection())]375 pub fn sponsor_collection(449 pub fn sponsor_collection(376 admin: OriginFor<T>,450 admin: OriginFor<T>,385 T::CollectionHandler::set_sponsor(Self::account_id(), collection_id)459 T::CollectionHandler::set_sponsor(Self::account_id(), collection_id)386 }460 }461462 /// Removes the pallet as the sponsor for the collection.463 /// Returns [`NoPermission`][`Error::NoPermission`]464 /// if the pallet wasn't the sponsor.465 ///466 /// # Permissions467 ///468 /// * Pallet admin469 ///470 /// # Arguments471 ///472 /// * `collection_id`: ID of the collection that is sponsored by `pallet_id`387 #[pallet::weight(T::WeightInfo::stop_sponsoring_collection())]473 #[pallet::weight(T::WeightInfo::stop_sponsoring_collection())]388 pub fn stop_sponsoring_collection(474 pub fn stop_sponsoring_collection(389 admin: OriginFor<T>,475 admin: OriginFor<T>,404 T::CollectionHandler::remove_collection_sponsor(collection_id)490 T::CollectionHandler::remove_collection_sponsor(collection_id)405 }491 }406492493 /// Sets the pallet to be the sponsor for the contract.494 ///495 /// # Permissions496 ///497 /// * Pallet admin498 ///499 /// # Arguments500 ///501 /// * `contract_id`: the contract address that will be sponsored by `pallet_id`407 #[pallet::weight(T::WeightInfo::sponsor_contract())]502 #[pallet::weight(T::WeightInfo::sponsor_contract())]408 pub fn sponsor_contract(admin: OriginFor<T>, contract_id: H160) -> DispatchResult {503 pub fn sponsor_contract(admin: OriginFor<T>, contract_id: H160) -> DispatchResult {409 let admin_id = ensure_signed(admin)?;504 let admin_id = ensure_signed(admin)?;419 )514 )420 }515 }421516517 /// Removes the pallet as the sponsor for the contract.518 /// Returns [`NoPermission`][`Error::NoPermission`]519 /// if the pallet wasn't the sponsor.520 ///521 /// # Permissions522 ///523 /// * Pallet admin524 ///525 /// # Arguments526 ///527 /// * `contract_id`: the contract address that is sponsored by `pallet_id`422 #[pallet::weight(T::WeightInfo::stop_sponsoring_contract())]528 #[pallet::weight(T::WeightInfo::stop_sponsoring_contract())]423 pub fn stop_sponsoring_contract(admin: OriginFor<T>, contract_id: H160) -> DispatchResult {529 pub fn stop_sponsoring_contract(admin: OriginFor<T>, contract_id: H160) -> DispatchResult {424 let admin_id = ensure_signed(admin)?;530 let admin_id = ensure_signed(admin)?;437 T::ContractHandler::remove_contract_sponsor(contract_id)543 T::ContractHandler::remove_contract_sponsor(contract_id)438 }544 }439545546 /// Recalculates interest for the specified number of stakers.547 /// If all stakers are not recalculated, the next call of the extrinsic548 /// will continue the recalculation, from those stakers for whom this549 /// was not perform in last call.550 ///551 /// # Permissions552 ///553 /// * Pallet admin554 ///555 /// # Arguments556 ///557 /// * `stakers_number`: the number of stakers for which recalculation will be performed440 #[pallet::weight(T::WeightInfo::payout_stakers(stakers_number.unwrap_or(20) as u32))]558 #[pallet::weight(T::WeightInfo::payout_stakers(stakers_number.unwrap_or(20) as u32))]441 pub fn payout_stakers(admin: OriginFor<T>, stakers_number: Option<u8>) -> DispatchResult {559 pub fn payout_stakers(admin: OriginFor<T>, stakers_number: Option<u8>) -> DispatchResult {442 let admin_id = ensure_signed(admin)?;560 let admin_id = ensure_signed(admin)?;446 Error::<T>::NoPermission564 Error::<T>::NoPermission447 );565 );448566567 // calculate the number of the current recalculation block,568 // this is necessary in order to understand which stakers we should calculate interest449 let current_recalc_block =569 let current_recalc_block =450 Self::get_current_recalc_block(T::RelayBlockNumberProvider::current_block_number());570 Self::get_current_recalc_block(T::RelayBlockNumberProvider::current_block_number());571572 // calculate the number of the next recalculation block,573 // this value is set for the stakers to whom the recalculation will be performed451 let next_recalc_block = current_recalc_block + T::RecalculationInterval::get();574 let next_recalc_block = current_recalc_block + T::RecalculationInterval::get();452575453 let mut storage_iterator = Self::get_next_calculated_key()576 let mut storage_iterator = Self::get_next_calculated_key()454 .map_or(Staked::<T>::iter(), |key| Staked::<T>::iter_from(key));577 .map_or(Staked::<T>::iter(), |key| Staked::<T>::iter_from(key));455578456 NextCalculatedRecord::<T>::set(None);579 NextCalculatedRecord::<T>::set(None);457458 // {459 // let mut stakers_number = stakers_number.unwrap_or(20);460 // let mut last_id = admin_id;461 // let mut income_acc = BalanceOf::<T>::default();462 // let mut amount_acc = BalanceOf::<T>::default();463464 // while let Some((465 // (current_id, staked_block),466 // (amount, next_recalc_block_for_stake),467 // )) = storage_iterator.next()468 // {469 // if last_id != current_id {470 // if income_acc != BalanceOf::<T>::default() {471 // <T::Currency as Currency<T::AccountId>>::transfer(472 // &T::TreasuryAccountId::get(),473 // &last_id,474 // income_acc,475 // ExistenceRequirement::KeepAlive,476 // )477 // .and_then(|_| Self::add_lock_balance(&last_id, income_acc))?;478479 // Self::deposit_event(Event::StakingRecalculation(480 // last_id, amount, income_acc,481 // ));482 // }483484 // if stakers_number == 0 {485 // NextCalculatedRecord::<T>::set(Some((current_id, staked_block)));486 // break;487 // }488 // stakers_number -= 1;489 // income_acc = BalanceOf::<T>::default();490 // last_id = current_id;491 // };492 // if current_recalc_block >= next_recalc_block_for_stake {493 // Self::recalculate_and_insert_stake(494 // &last_id,495 // staked_block,496 // next_recalc_block,497 // amount,498 // ((current_recalc_block - next_recalc_block_for_stake)499 // / T::RecalculationInterval::get())500 // .into() + 1,501 // &mut income_acc,502 // );503 // }504 // }505 // }506580507 {581 {508 let mut stakers_number = stakers_number.unwrap_or(20);582 let mut stakers_number = stakers_number.unwrap_or(20);509 let last_id = RefCell::new(None);583 let last_id = RefCell::new(None);510 let income_acc = RefCell::new(BalanceOf::<T>::default());584 let income_acc = RefCell::new(BalanceOf::<T>::default());511 let amount_acc = RefCell::new(BalanceOf::<T>::default());585 let amount_acc = RefCell::new(BalanceOf::<T>::default());512586587 // this closure is used to perform some of the actions if we break the loop because we reached the number of stakers for recalculation,588 // but there were unrecalculated records in the storage.513 let flush_stake = || -> DispatchResult {589 let flush_stake = || -> DispatchResult {514 if let Some(last_id) = &*last_id.borrow() {590 if let Some(last_id) = &*last_id.borrow() {515 if !income_acc.borrow().is_zero() {591 if !income_acc.borrow().is_zero() {578}654}579655580impl<T: Config> Pallet<T> {656impl<T: Config> Pallet<T> {657 /// The account address of the app promotion pot.658 ///659 /// This actually does computation. If you need to keep using it, then make sure you cache the660 /// value and only call this once.581 pub fn account_id() -> T::AccountId {661 pub fn account_id() -> T::AccountId {582 T::PalletId::get().into_account_truncating()662 T::PalletId::get().into_account_truncating()583 }663 }584664665 /// Unlocks the balance that was locked by the pallet.666 ///667 /// - `staker`: staker account.668 /// - `amount`: amount of unlocked funds.585 fn unlock_balance(staker: &T::AccountId, amount: BalanceOf<T>) -> DispatchResult {669 fn unlock_balance(staker: &T::AccountId, amount: BalanceOf<T>) -> DispatchResult {586 let locked_balance = Self::get_locked_balance(staker)670 let locked_balance = Self::get_locked_balance(staker)587 .map(|l| l.amount)671 .map(|l| l.amount)598 Ok(())682 Ok(())599 }683 }600684685 /// Adds the balance to locked by the pallet.686 ///687 /// - `staker`: staker account.688 /// - `amount`: amount of added locked funds.601 fn add_lock_balance(staker: &T::AccountId, amount: BalanceOf<T>) -> DispatchResult {689 fn add_lock_balance(staker: &T::AccountId, amount: BalanceOf<T>) -> DispatchResult {602 Self::get_locked_balance(staker)690 Self::get_locked_balance(staker)603 .map_or(<BalanceOf<T>>::default(), |l| l.amount)691 .map_or(<BalanceOf<T>>::default(), |l| l.amount)606 .ok_or(ArithmeticError::Overflow.into())694 .ok_or(ArithmeticError::Overflow.into())607 }695 }608696697 /// Sets the new state of a balance locked by the pallet.698 ///699 /// - `staker`: staker account.700 /// - `amount`: amount of locked funds.609 fn set_lock_unchecked(staker: &T::AccountId, amount: BalanceOf<T>) {701 fn set_lock_unchecked(staker: &T::AccountId, amount: BalanceOf<T>) {610 if amount.is_zero() {702 if amount.is_zero() {611 <T::Currency as LockableCurrency<T::AccountId>>::remove_lock(LOCK_IDENTIFIER, &staker);703 <T::Currency as LockableCurrency<T::AccountId>>::remove_lock(LOCK_IDENTIFIER, &staker);619 }711 }620 }712 }621713714 /// Returns the balance locked by the pallet for the staker.715 ///716 /// - `staker`: staker account.622 pub fn get_locked_balance(717 pub fn get_locked_balance(623 staker: impl EncodeLike<T::AccountId>,718 staker: impl EncodeLike<T::AccountId>,624 ) -> Option<BalanceLock<BalanceOf<T>>> {719 ) -> Option<BalanceLock<BalanceOf<T>>> {627 .find(|l| l.id == LOCK_IDENTIFIER)722 .find(|l| l.id == LOCK_IDENTIFIER)628 }723 }629724725 /// Returns the total staked balance for the staker.726 ///727 /// - `staker`: staker account.630 pub fn total_staked_by_id(staker: impl EncodeLike<T::AccountId>) -> Option<BalanceOf<T>> {728 pub fn total_staked_by_id(staker: impl EncodeLike<T::AccountId>) -> Option<BalanceOf<T>> {631 let staked = Staked::<T>::iter_prefix((staker,))729 let staked = Staked::<T>::iter_prefix((staker,))632 .into_iter()730 .into_iter()640 }738 }641 }739 }642740741 /// Returns all relay block numbers when stake was made,742 /// the amount of the stake.743 ///744 /// - `staker`: staker account.643 pub fn total_staked_by_id_per_block(745 pub fn total_staked_by_id_per_block(644 staker: impl EncodeLike<T::AccountId>,746 staker: impl EncodeLike<T::AccountId>,645 ) -> Option<Vec<(T::BlockNumber, BalanceOf<T>)>> {747 ) -> Option<Vec<(T::BlockNumber, BalanceOf<T>)>> {655 }757 }656 }758 }657759760 /// Returns the total staked balance for the staker.761 /// If `staker` is `None`, returns the total amount staked.762 /// - `staker`: staker account.658 pub fn cross_id_total_staked(staker: Option<T::CrossAccountId>) -> Option<BalanceOf<T>> {763 pub fn cross_id_total_staked(staker: Option<T::CrossAccountId>) -> Option<BalanceOf<T>> {659 staker.map_or(Some(<TotalStaked<T>>::get()), |s| {764 staker.map_or(Some(<TotalStaked<T>>::get()), |s| {660 Self::total_staked_by_id(s.as_sub())765 Self::total_staked_by_id(s.as_sub())667 // .unwrap_or_default()772 // .unwrap_or_default()668 // }773 // }669774775 /// Returns all relay block numbers when stake was made,776 /// the amount of the stake.777 ///778 /// - `staker`: staker account.670 pub fn cross_id_total_staked_per_block(779 pub fn cross_id_total_staked_per_block(671 staker: T::CrossAccountId,780 staker: T::CrossAccountId,672 ) -> Vec<(T::BlockNumber, BalanceOf<T>)> {781 ) -> Vec<(T::BlockNumber, BalanceOf<T>)> {704 (current_relay_block / T::RecalculationInterval::get()) * T::RecalculationInterval::get()813 (current_relay_block / T::RecalculationInterval::get()) * T::RecalculationInterval::get()705 }814 }706707 // fn get_next_recalc_block(current_relay_block: T::BlockNumber) -> T::BlockNumber {708 // Self::get_current_recalc_block(current_relay_block) + T::RecalculationInterval::get()709 // }710815711 fn get_next_calculated_key() -> Option<Vec<u8>> {816 fn get_next_calculated_key() -> Option<Vec<u8>> {712 Self::get_next_calculated_record().map(|key| Staked::<T>::hashed_key_for(key))817 Self::get_next_calculated_record().map(|key| Staked::<T>::hashed_key_for(key))717where822where718 <<T as Config>::Currency as Currency<T::AccountId>>::Balance: Sum,823 <<T as Config>::Currency as Currency<T::AccountId>>::Balance: Sum,719{824{825 /// Returns the amount reserved by the pending.826 /// If `staker` is `None`, returns the total pending.827 ///828 /// -`staker`: staker account.829 ///720 /// Since user funds are not transferred anywhere by staking, overflow protection is provided830 /// Since user funds are not transferred anywhere by staking, overflow protection is provided721 /// at the level of the associated type `Balance` of `Currency` trait. In order to overflow,831 /// at the level of the associated type `Balance` of `Currency` trait. In order to overflow,722 /// the staker must have more funds on his account than the maximum set for `Balance` type.832 /// the staker must have more funds on his account than the maximum set for `Balance` type.740 )850 )741 }851 }742852853 /// Returns all parachain block numbers when unreserve is expected,854 /// the amount of the unreserved funds.855 ///856 /// - `staker`: staker account.743 pub fn cross_id_pending_unstake_per_block(857 pub fn cross_id_pending_unstake_per_block(744 staker: T::CrossAccountId,858 staker: T::CrossAccountId,745 ) -> Vec<(T::BlockNumber, BalanceOf<T>)> {859 ) -> Vec<(T::BlockNumber, BalanceOf<T>)> {pallets/app-promotion/src/types.rsdiffbeforeafterboth9use sp_std::borrow::ToOwned;9use sp_std::borrow::ToOwned;10use pallet_evm_contract_helpers::{Pallet as EvmHelpersPallet, Config as EvmHelpersConfig};10use pallet_evm_contract_helpers::{Pallet as EvmHelpersPallet, Config as EvmHelpersConfig};111112/// This trait was defined because `LockableCurrency`13/// has no way to know the state of the lock for an account.12pub trait ExtendedLockableCurrency<AccountId: Parameter>: LockableCurrency<AccountId> {14pub trait ExtendedLockableCurrency<AccountId: Parameter>: LockableCurrency<AccountId> {15 /// Returns lock balance for an account. Allows to determine the cause of the lock.13 fn locks<KArg>(who: KArg) -> WeakBoundedVec<BalanceLock<Self::Balance>, Self::MaxLocks>16 fn locks<KArg>(who: KArg) -> WeakBoundedVec<BalanceLock<Self::Balance>, Self::MaxLocks>14 where17 where15 KArg: EncodeLike<AccountId>;18 KArg: EncodeLike<AccountId>;25 Self::locks(who)28 Self::locks(who)26 }29 }27}30}2831/// Trait for interacting with collections.29pub trait CollectionHandler {32pub trait CollectionHandler {30 type CollectionId;33 type CollectionId;31 type AccountId;34 type AccountId;323536 /// Sets sponsor for a collection.37 ///38 /// - `sponsor_id`: the account of the sponsor-to-be.39 /// - `collection_id`: ID of the modified collection.33 fn set_sponsor(40 fn set_sponsor(34 sponsor_id: Self::AccountId,41 sponsor_id: Self::AccountId,35 collection_id: Self::CollectionId,42 collection_id: Self::CollectionId,36 ) -> DispatchResult;43 ) -> DispatchResult;374445 /// Removes sponsor for a collection.46 ///47 /// - `collection_id`: ID of the modified collection.38 fn remove_collection_sponsor(collection_id: Self::CollectionId) -> DispatchResult;48 fn remove_collection_sponsor(collection_id: Self::CollectionId) -> DispatchResult;394950 /// Retuns the current sponsor for a collection if one is set.51 ///52 /// - `collection_id`: ID of the collection.40 fn sponsor(collection_id: Self::CollectionId)53 fn sponsor(collection_id: Self::CollectionId)41 -> Result<Option<Self::AccountId>, DispatchError>;54 -> Result<Option<Self::AccountId>, DispatchError>;42}55}66 .map(|acc| acc.to_owned()))79 .map(|acc| acc.to_owned()))67 }80 }68}81}6982/// Trait for interacting with contracts.70pub trait ContractHandler {83pub trait ContractHandler {71 type ContractId;84 type ContractId;72 type AccountId;85 type AccountId;738687 /// Sets sponsor for a contract.88 ///89 /// - `sponsor_id`: the account of the sponsor-to-be.90 /// - `contract_address`: the address of the modified contract.74 fn set_sponsor(91 fn set_sponsor(75 sponsor_id: Self::AccountId,92 sponsor_id: Self::AccountId,76 contract_address: Self::ContractId,93 contract_address: Self::ContractId,77 ) -> DispatchResult;94 ) -> DispatchResult;789596 /// Removes sponsor for a contract.97 ///98 /// - `contract_address`: the address of the modified contract.79 fn remove_contract_sponsor(contract_address: Self::ContractId) -> DispatchResult;99 fn remove_contract_sponsor(contract_address: Self::ContractId) -> DispatchResult;80100101 /// Retuns the current sponsor for a contract if one is set.102 ///103 /// - `contract_address`: the contract address.81 fn sponsor(104 fn sponsor(82 contract_address: Self::ContractId,105 contract_address: Self::ContractId,83 ) -> Result<Option<Self::AccountId>, DispatchError>;106 ) -> Result<Option<Self::AccountId>, DispatchError>;pallets/evm-contract-helpers/CHANGELOG.mddiffbeforeafterboth223All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.445## [v0.3.0] 2022-09-0567### Added89- Methods `force_set_sponsor` , `force_remove_sponsor` to be able to administer sponsorships with other pallets. Added to implement `AppPromotion` pallet logic.105## [v0.2.0] - 2022-08-1911## [v0.2.0] - 2022-08-196127### Added13### Added8149 - Set arbitrary evm address as contract sponsor.15- Set arbitrary evm address as contract sponsor.10 - Ability to remove current sponsor.16- Ability to remove current sponsor.111712### Removed18### Removed13 - Remove methods14 + sponsoring_enabled15 + toggle_sponsoring161917 ### Changed20- Remove methods21 - sponsoring_enabled22 - toggle_sponsoring182319 - Change `toggle_sponsoring` to `self_sponsored_enable`.24### Changed202526- Change `toggle_sponsoring` to `self_sponsored_enable`.212722## [v0.1.2] 2022-08-1628## [v0.1.2] 2022-08-16232924### Other changes30### Other changes253126- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a32- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a273328- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf834- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8293530- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b36- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b37pallets/evm-contract-helpers/Cargo.tomldiffbeforeafterboth1[package]1[package]2name = "pallet-evm-contract-helpers"2name = "pallet-evm-contract-helpers"3version = "0.2.0"3version = "0.3.0"4license = "GPLv3"4license = "GPLv3"5edition = "2021"5edition = "2021"66pallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth216 Ok(())216 Ok(())217 }217 }218218219 /// TO-DO219 /// Force set `sponsor` for `contract`.220 ///220 ///221 ///221 /// Differs from `set_sponsor` in that confirmation222 /// from the sponsor is not required.222 pub fn force_set_sponsor(223 pub fn force_set_sponsor(223 contract_address: H160,224 contract_address: H160,224 sponsor: &T::CrossAccountId,225 sponsor: &T::CrossAccountId,269 Self::force_remove_sponsor(contract_address)270 Self::force_remove_sponsor(contract_address)270 }271 }271272272 /// TO-DO273 /// Force remove `sponsor` for `contract`.273 ///274 ///274 ///275 /// Differs from `remove_sponsor` in that276 /// it doesn't require consent from the `owner` of the contract.275 pub fn force_remove_sponsor(contract_address: H160) -> DispatchResult {277 pub fn force_remove_sponsor(contract_address: H160) -> DispatchResult {276 Sponsoring::<T>::remove(contract_address);278 Sponsoring::<T>::remove(contract_address);277279pallets/unique/CHANGELOG.mddiffbeforeafterboth445<!-- bureaucrate goes here -->5<!-- bureaucrate goes here -->667## [v0.1.4] 2022-09-57## [v0.1.4] 2022-09-05889### Added9### Added1010pallets/unique/src/lib.rsdiffbeforeafterboth1105}1105}110611061107impl<T: Config> Pallet<T> {1107impl<T: Config> Pallet<T> {1108 /// Force set `sponsor` for `collection`.1109 ///1110 /// Differs from [`set_collection_sponsor`][`Pallet::set_collection_sponsor`] in that confirmation1111 /// from the `sponsor` is not required.1112 ///1113 /// # Arguments1114 ///1115 /// * `sponsor`: ID of the account of the sponsor-to-be.1116 /// * `collection_id`: ID of the modified collection.1108 pub fn force_set_sponsor(sponsor: T::AccountId, collection_id: CollectionId) -> DispatchResult {1117 pub fn force_set_sponsor(sponsor: T::AccountId, collection_id: CollectionId) -> DispatchResult {1109 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1118 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1110 target_collection.check_is_internal()?;1119 target_collection.check_is_internal()?;1125 target_collection.save()1134 target_collection.save()1126 }1135 }112711361137 /// Force remove `sponsor` for `collection`.1138 ///1139 /// Differs from `remove_sponsor` in that1140 /// it doesn't require consent from the `owner` of the collection.1141 ///1142 /// # Arguments1143 ///1144 /// * `collection_id`: ID of the modified collection.1128 pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult {1145 pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult {1129 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1146 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1130 target_collection.check_is_internal()?;1147 target_collection.check_is_internal()?;primitives/common/CHANGELOG.mddiffbeforeafterboth1<!-- bureaucrate goes here -->1<!-- bureaucrate goes here -->2## [v0.9.27] 2022-09-0834### Added5- Relay block constants. In particular, it is necessary to add the `AppPromotion` pallet at runtime.62## [v0.9.25] 2022-08-167## [v0.9.25] 2022-08-16384### Other changes9### Other changesruntime/opal/CHANGELOG.mddiffbeforeafterboth3All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.445<!-- bureaucrate goes here -->5<!-- bureaucrate goes here -->67## [v0.9.27] 2022-09-0889### Added1011- `AppPromotion` pallet to runtime.126## [v0.9.27] 2022-08-1613## [v0.9.27] 2022-08-167148### Bugfixes15### Bugfixes91610- Add missing config keys 74f532ac28dce15c15e7d576c074a58eba658c0817- Add missing config keys 74f532ac28dce15c15e7d576c074a58eba658c08111812### Other changes19### Other changes132014- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a21- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a152216- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf823- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8172418- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b25- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b1926runtime/quartz/CHANGELOG.mddiffbeforeafterboth3All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.445<!-- bureaucrate goes here -->5<!-- bureaucrate goes here -->67## [v0.9.27] 2022-09-0889### Added1011- `AppPromotion` pallet to runtime.126## [v0.9.27] 2022-08-1613## [v0.9.27] 2022-08-167148### Bugfixes15### Bugfixes91610- Add missing config keys 74f532ac28dce15c15e7d576c074a58eba658c0817- Add missing config keys 74f532ac28dce15c15e7d576c074a58eba658c08111812### Other changes19### Other changes1314- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a152016- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf821- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a172218- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b23- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8192425- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b2026runtime/unique/CHANGELOG.mddiffbeforeafterboth3All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.445<!-- bureaucrate goes here -->5<!-- bureaucrate goes here -->67## [v0.9.27] 2022-09-0889### Added1011- `AppPromotion` pallet to runtime.126## [v0.9.27] 2022-08-1613## [v0.9.27] 2022-08-167148### Bugfixes15### Bugfixes91610- Add missing config keys 74f532ac28dce15c15e7d576c074a58eba658c0817- Add missing config keys 74f532ac28dce15c15e7d576c074a58eba658c08111812### Other changes19### Other changes132014- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a21- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a152216- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf823- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8172418- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b25- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b1926