difftreelog
added bench for sponsoring, logic broken , commit for rebase
in: master
14 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5307,6 +5307,7 @@
"pallet-common",
"pallet-evm",
"pallet-evm-contract-helpers",
+ "pallet-evm-migration",
"pallet-randomness-collective-flip",
"pallet-timestamp",
"pallet-unique",
pallets/app-promotion/Cargo.tomldiffbeforeafterboth--- a/pallets/app-promotion/Cargo.toml
+++ b/pallets/app-promotion/Cargo.toml
@@ -15,7 +15,7 @@
targets = ['x86_64-unknown-linux-gnu']
[features]
-default = ['std']
+default = ['std',]
runtime-benchmarks = [
'frame-benchmarking',
'frame-support/runtime-benchmarks',
@@ -121,6 +121,13 @@
[dependencies.pallet-evm-contract-helpers]
default-features = false
path = "../evm-contract-helpers"
+
+[dev-dependencies]
+[dependencies.pallet-evm-migration]
+default-features = false
+path = "../evm-migration"
+
+
################################################################################
[dependencies]
pallets/app-promotion/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/app-promotion/src/benchmarking.rs
+++ b/pallets/app-promotion/src/benchmarking.rs
@@ -20,53 +20,109 @@
use crate::Pallet as PromototionPallet;
use sp_runtime::traits::Bounded;
+use sp_std::vec;
use frame_benchmarking::{benchmarks, account};
-use frame_support::traits::OnInitialize;
+
use frame_system::{Origin, RawOrigin};
+use pallet_unique::benchmarking::create_nft_collection;
+use pallet_evm_migration::Pallet as EvmMigrationPallet;
+
+// trait BenchmarkingConfig: Config + pallet_unique::Config { }
+
+// impl<T: Config + pallet_unique::Config> BenchmarkingConfig for T { }
const SEED: u32 = 0;
benchmarks! {
where_clause{
- where T: Config
-
+ where T: Config + pallet_unique::Config + pallet_evm_migration::Config ,
+ T::BlockNumber: From<u32>
}
- on_initialize {
- let block1: T::BlockNumber = T::BlockNumber::from(1u32);
- let block2: T::BlockNumber = T::BlockNumber::from(2u32);
- PromototionPallet::<T>::on_initialize(block1); // Create Treasury account
- }: { PromototionPallet::<T>::on_initialize(block2); } // Benchmark deposit_into_existing path
-
start_app_promotion {
- let caller = account::<T::AccountId>("caller", 0, SEED);
- } : {PromototionPallet::<T>::start_app_promotion(RawOrigin::Root.into(), T::BlockNumber::from(2u32))?}
+ } : {PromototionPallet::<T>::start_app_promotion(RawOrigin::Root.into(), None)?}
+
+ stop_app_promotion{
+ PromototionPallet::<T>::start_app_promotion(RawOrigin::Root.into(), Some(25.into()))?;
+ } : {PromototionPallet::<T>::stop_app_promotion(RawOrigin::Root.into())?}
set_admin_address {
- let caller = account::<T::AccountId>("caller", 0, SEED);
- let _ = T::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
- } : {PromototionPallet::<T>::set_admin_address(RawOrigin::Root.into(), caller)?}
+ let pallet_admin = account::<T::AccountId>("admin", 0, SEED);
+ let _ = <T as Config>::Currency::make_free_balance_be(&pallet_admin, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+ } : {PromototionPallet::<T>::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin))?}
+ payout_stakers{
+ let pallet_admin = account::<T::AccountId>("admin", 0, SEED);
+ let share = Perbill::from_rational(1u32, 10);
+ PromototionPallet::<T>::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?;
+ let _ = <T as Config>::Currency::make_free_balance_be(&pallet_admin, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+ let staker: T::AccountId = account("caller", 0, SEED);
+ let _ = <T as Config>::Currency::make_free_balance_be(&staker, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+ let _ = PromototionPallet::<T>::stake(RawOrigin::Signed(staker.clone()).into(), share * <T as Config>::Currency::total_balance(&staker))?;
+ } : {PromototionPallet::<T>::payout_stakers(RawOrigin::Signed(pallet_admin.clone()).into(), Some(1))?}
+
stake {
let caller = account::<T::AccountId>("caller", 0, SEED);
let share = Perbill::from_rational(1u32, 10);
- let _ = T::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
- } : {PromototionPallet::<T>::stake(RawOrigin::Signed(caller.clone()).into(), share * T::Currency::total_balance(&caller))?}
+ let _ = <T as Config>::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+ } : {PromototionPallet::<T>::stake(RawOrigin::Signed(caller.clone()).into(), share * <T as Config>::Currency::total_balance(&caller))?}
unstake {
let caller = account::<T::AccountId>("caller", 0, SEED);
let share = Perbill::from_rational(1u32, 10);
- let _ = T::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
- let _ = PromototionPallet::<T>::stake(RawOrigin::Signed(caller.clone()).into(), share * T::Currency::total_balance(&caller))?;
+ let _ = <T as Config>::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+ let _ = PromototionPallet::<T>::stake(RawOrigin::Signed(caller.clone()).into(), share * <T as Config>::Currency::total_balance(&caller))?;
- } : {PromototionPallet::<T>::unstake(RawOrigin::Signed(caller.clone()).into(), share * T::Currency::total_balance(&caller))?}
+ } : {PromototionPallet::<T>::unstake(RawOrigin::Signed(caller.clone()).into(), share * <T as Config>::Currency::total_balance(&caller))?}
recalculate_stake {
let caller = account::<T::AccountId>("caller", 0, SEED);
let share = Perbill::from_rational(1u32, 10);
- let _ = T::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
- let _ = PromototionPallet::<T>::stake(RawOrigin::Signed(caller.clone()).into(), share * T::Currency::total_balance(&caller))?;
- let block = <T::BlockNumberProvider as BlockNumberProvider>::current_block_number();
+ let _ = <T as Config>::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+ let _ = PromototionPallet::<T>::stake(RawOrigin::Signed(caller.clone()).into(), share * <T as Config>::Currency::total_balance(&caller))?;
+ let block = <T::RelayBlockNumberProvider as BlockNumberProvider>::current_block_number();
let mut acc = <BalanceOf<T>>::default();
- } : {PromototionPallet::<T>::recalculate_stake(&caller, block, share * T::Currency::total_balance(&caller), &mut acc)}
+ } : {PromototionPallet::<T>::recalculate_stake(&caller, block, share * <T as Config>::Currency::total_balance(&caller), &mut acc)}
+
+ sponsor_collection {
+ let pallet_admin = account::<T::AccountId>("admin", 0, SEED);
+ PromototionPallet::<T>::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?;
+ let _ = <T as Config>::Currency::make_free_balance_be(&pallet_admin, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+ let caller: T::AccountId = account("caller", 0, SEED);
+ let _ = <T as Config>::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+ let collection = create_nft_collection::<T>(caller.clone())?;
+ } : {PromototionPallet::<T>::sponsor_collection(RawOrigin::Signed(pallet_admin.clone()).into(), collection)?}
+
+ stop_sponsoring_collection {
+ let pallet_admin = account::<T::AccountId>("admin", 0, SEED);
+ PromototionPallet::<T>::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?;
+ let _ = <T as Config>::Currency::make_free_balance_be(&pallet_admin, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+ let caller: T::AccountId = account("caller", 0, SEED);
+ let _ = <T as Config>::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+ let collection = create_nft_collection::<T>(caller.clone())?;
+ PromototionPallet::<T>::sponsor_collection(RawOrigin::Signed(pallet_admin.clone()).into(), collection)?;
+ } : {PromototionPallet::<T>::stop_sponsoring_collection(RawOrigin::Signed(pallet_admin.clone()).into(), collection)?}
+
+ sponsor_contract {
+ let pallet_admin = account::<T::AccountId>("admin", 0, SEED);
+ PromototionPallet::<T>::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?;
+
+ let _ = <T as Config>::Currency::make_free_balance_be(&pallet_admin, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+ let address = H160::from_low_u64_be(SEED as u64);
+ let data: Vec<u8> = (0..20 as u8).collect();
+ <EvmMigrationPallet<T>>::begin(RawOrigin::Root.into(), address)?;
+ <EvmMigrationPallet<T>>::finish(RawOrigin::Root.into(), address, data)?;
+ } : {PromototionPallet::<T>::sponsor_conract(RawOrigin::Signed(pallet_admin.clone()).into(), address)?}
+
+ stop_sponsoring_contract {
+ let pallet_admin = account::<T::AccountId>("admin", 0, SEED);
+ PromototionPallet::<T>::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?;
+
+ let _ = <T as Config>::Currency::make_free_balance_be(&pallet_admin, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+ let address = H160::from_low_u64_be(SEED as u64);
+ let data: Vec<u8> = (0..20 as u8).collect();
+ <EvmMigrationPallet<T>>::begin(RawOrigin::Root.into(), address)?;
+ <EvmMigrationPallet<T>>::finish(RawOrigin::Root.into(), address, data)?;
+ PromototionPallet::<T>::sponsor_conract(RawOrigin::Signed(pallet_admin.clone()).into(), address)?;
+ } : {PromototionPallet::<T>::stop_sponsoring_contract(RawOrigin::Signed(pallet_admin.clone()).into(), address)?}
}
pallets/app-promotion/src/lib.rsdiffbeforeafterboth--- a/pallets/app-promotion/src/lib.rs
+++ b/pallets/app-promotion/src/lib.rs
@@ -132,6 +132,8 @@
#[pallet::generate_deposit(fn deposit_event)]
pub enum Event<T: Config> {
StakingRecalculation(
+ /// An recalculated staker
+ T::AccountId,
/// Base on which interest is calculated
BalanceOf<T>,
/// Amount of accrued interest
@@ -164,7 +166,7 @@
Key<Blake2_128Concat, T::AccountId>,
Key<Twox64Concat, T::BlockNumber>,
),
- Value = BalanceOf<T>,
+ Value = (BalanceOf<T>, T::BlockNumber),
QueryKind = ValueQuery,
>;
@@ -189,6 +191,13 @@
pub type NextInterestBlock<T: Config> =
StorageValue<Value = T::BlockNumber, QueryKind = ValueQuery>;
+ /// Stores the address of the staker for which the last revenue recalculation was performed.
+ /// If `None`, then recalculation has not yet been performed or calculations have been completed for all stakers.
+ #[pallet::storage]
+ #[pallet::getter(fn get_last_calculated_staker)]
+ pub type LastCalcucaltedStaker<T: Config> =
+ StorageValue<Value = T::AccountId, QueryKind = OptionQuery>;
+
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_initialize(current_block: T::BlockNumber) -> Weight
@@ -196,10 +205,10 @@
<T as frame_system::Config>::BlockNumber: From<u32>,
{
let mut consumed_weight = 0;
- let mut add_weight = |reads, writes, weight| {
- consumed_weight += T::DbWeight::get().reads_writes(reads, writes);
- consumed_weight += weight;
- };
+ // let mut add_weight = |reads, writes, weight| {
+ // consumed_weight += T::DbWeight::get().reads_writes(reads, writes);
+ // consumed_weight += weight;
+ // };
PendingUnstake::<T>::iter()
.filter_map(|((staker, block), amount)| {
@@ -214,41 +223,44 @@
<PendingUnstake<T>>::remove((staker, block));
});
- let next_interest_block = Self::get_interest_block();
- let current_relay_block = T::RelayBlockNumberProvider::current_block_number();
- if next_interest_block != 0.into() && current_relay_block >= next_interest_block {
- let mut acc = <BalanceOf<T>>::default();
- let mut base_acc = <BalanceOf<T>>::default();
+ // let next_interest_block = Self::get_interest_block();
+ // let current_relay_block = T::RelayBlockNumberProvider::current_block_number();
+ // if next_interest_block != 0.into() && current_relay_block >= next_interest_block {
+ // let mut acc = <BalanceOf<T>>::default();
+ // let mut base_acc = <BalanceOf<T>>::default();
- NextInterestBlock::<T>::set(
- NextInterestBlock::<T>::get() + T::RecalculationInterval::get(),
- );
- add_weight(0, 1, 0);
+ // NextInterestBlock::<T>::set(
+ // NextInterestBlock::<T>::get() + T::RecalculationInterval::get(),
+ // );
+ // add_weight(0, 1, 0);
- Staked::<T>::iter()
- .filter(|((_, block), _)| {
- *block + T::RecalculationInterval::get() <= current_relay_block
- })
- .for_each(|((staker, block), amount)| {
- Self::recalculate_stake(&staker, block, amount, &mut acc);
- add_weight(0, 0, T::WeightInfo::recalculate_stake());
- base_acc += amount;
- });
- <TotalStaked<T>>::get()
- .checked_add(&acc)
- .map(|res| <TotalStaked<T>>::set(res));
+ // Staked::<T>::iter()
+ // .filter(|((_, block), _)| {
+ // *block + T::RecalculationInterval::get() <= current_relay_block
+ // })
+ // .for_each(|((staker, block), amount)| {
+ // Self::recalculate_stake(&staker, block, amount, &mut acc);
+ // add_weight(0, 0, T::WeightInfo::recalculate_stake());
+ // base_acc += amount;
+ // });
+ // <TotalStaked<T>>::get()
+ // .checked_add(&acc)
+ // .map(|res| <TotalStaked<T>>::set(res));
- Self::deposit_event(Event::StakingRecalculation(base_acc, acc));
- add_weight(0, 1, 0);
- } else {
- add_weight(1, 0, 0)
- };
+ // Self::deposit_event(Event::StakingRecalculation(base_acc, acc));
+ // add_weight(0, 1, 0);
+ // } else {
+ // add_weight(1, 0, 0)
+ // };
consumed_weight
}
}
#[pallet::call]
- impl<T: Config> Pallet<T> {
+ impl<T: Config> Pallet<T>
+ where
+ T::BlockNumber: From<u32>,
+ {
#[pallet::weight(T::WeightInfo::set_admin_address())]
pub fn set_admin_address(origin: OriginFor<T>, admin: T::CrossAccountId) -> DispatchResult {
ensure_root(origin)?;
@@ -281,7 +293,7 @@
Ok(())
}
- #[pallet::weight(0)]
+ #[pallet::weight(T::WeightInfo::stop_app_promotion())]
pub fn stop_app_promotion(origin: OriginFor<T>) -> DispatchResult
where
<T as frame_system::Config>::BlockNumber: From<u32>,
@@ -317,19 +329,24 @@
Self::add_lock_balance(&staker_id, amount)?;
let block_number = T::RelayBlockNumberProvider::current_block_number();
+ let recalc_block = (block_number / T::RecalculationInterval::get() + 2u32.into())
+ * T::RecalculationInterval::get();
- <Staked<T>>::insert(
- (&staker_id, block_number),
- <Staked<T>>::get((&staker_id, block_number))
+ <Staked<T>>::insert((&staker_id, block_number), {
+ let mut balance_and_recalc_block = <Staked<T>>::get((&staker_id, block_number));
+ balance_and_recalc_block.0 = balance_and_recalc_block
+ .0
.checked_add(&amount)
- .ok_or(ArithmeticError::Overflow)?,
- );
+ .ok_or(ArithmeticError::Overflow)?;
+ balance_and_recalc_block.1 = recalc_block;
+ balance_and_recalc_block
+ });
- <TotalStaked<T>>::set(
- <TotalStaked<T>>::get()
- .checked_add(&amount)
- .ok_or(ArithmeticError::Overflow)?,
- );
+ // <TotalStaked<T>>::set(
+ // <TotalStaked<T>>::get()
+ // .checked_add(&amount)
+ // .ok_or(ArithmeticError::Overflow)?,
+ // );
Ok(())
}
@@ -338,63 +355,120 @@
pub fn unstake(staker: OriginFor<T>, amount: BalanceOf<T>) -> DispatchResult {
let staker_id = ensure_signed(staker)?;
- let mut stakes = Staked::<T>::iter_prefix((&staker_id,)).collect::<Vec<_>>();
+ let mut stakes = Staked::<T>::drain_prefix((&staker_id,));
- let total_staked = stakes
- .iter()
- .fold(<BalanceOf<T>>::default(), |acc, (_, amount)| acc + *amount);
+ // let total_staked = stakes
+ // .iter()
+ // .fold(<BalanceOf<T>>::default(), |acc, (_, amount)| acc + *amount);
- ensure!(total_staked >= amount, ArithmeticError::Underflow);
+ // ensure!(total_staked >= amount, ArithmeticError::Underflow);
- <TotalStaked<T>>::set(
- <TotalStaked<T>>::get()
- .checked_sub(&amount)
- .ok_or(ArithmeticError::Underflow)?,
- );
+ // <TotalStaked<T>>::set(
+ // <TotalStaked<T>>::get()
+ // .checked_sub(&amount)
+ // .ok_or(ArithmeticError::Underflow)?,
+ // );
- let block =
- T::RelayBlockNumberProvider::current_block_number() + T::PendingInterval::get();
- <PendingUnstake<T>>::insert(
- (&staker_id, block),
- <PendingUnstake<T>>::get((&staker_id, block))
- .checked_add(&amount)
- .ok_or(ArithmeticError::Overflow)?,
- );
+ // let block =
+ // T::RelayBlockNumberProvider::current_block_number() + T::PendingInterval::get();
+ // <PendingUnstake<T>>::insert(
+ // (&staker_id, block),
+ // <PendingUnstake<T>>::get((&staker_id, block))
+ // .checked_add(&amount)
+ // .ok_or(ArithmeticError::Overflow)?,
+ // );
- stakes.sort_by_key(|(block, _)| *block);
+ // stakes.sort_by_key(|(block, _)| *block);
- let mut acc_amount = amount;
- let new_state = stakes
- .into_iter()
- .map_while(|(block, balance_per_block)| {
- if acc_amount == <BalanceOf<T>>::default() {
- return None;
- }
- if acc_amount <= balance_per_block {
- let res = (block, balance_per_block - acc_amount, acc_amount);
- acc_amount = <BalanceOf<T>>::default();
- return Some(res);
- } else {
- acc_amount -= balance_per_block;
- return Some((block, <BalanceOf<T>>::default(), acc_amount));
- }
- })
- .collect::<Vec<_>>();
+ // let mut acc_amount = amount;
+ // let new_state = stakes
+ // .into_iter()
+ // .map_while(|(block, balance_per_block)| {
+ // if acc_amount == <BalanceOf<T>>::default() {
+ // return None;
+ // }
+ // if acc_amount <= balance_per_block {
+ // let res = (block, balance_per_block - acc_amount, acc_amount);
+ // acc_amount = <BalanceOf<T>>::default();
+ // return Some(res);
+ // } else {
+ // acc_amount -= balance_per_block;
+ // return Some((block, <BalanceOf<T>>::default(), acc_amount));
+ // }
+ // })
+ // .collect::<Vec<_>>();
- new_state
- .into_iter()
- .for_each(|(block, to_staked, _to_pending)| {
- if to_staked == <BalanceOf<T>>::default() {
- <Staked<T>>::remove((&staker_id, block));
- } else {
- <Staked<T>>::insert((&staker_id, block), to_staked);
- }
- });
+ // new_state
+ // .into_iter()
+ // .for_each(|(block, to_staked, _to_pending)| {
+ // if to_staked == <BalanceOf<T>>::default() {
+ // <Staked<T>>::remove((&staker_id, block));
+ // } else {
+ // <Staked<T>>::insert((&staker_id, block), to_staked);
+ // }
+ // });
Ok(())
+
+ // let staker_id = ensure_signed(staker)?;
+
+ // let mut stakes = Staked::<T>::iter_prefix((&staker_id,)).collect::<Vec<_>>();
+
+ // let total_staked = stakes
+ // .iter()
+ // .fold(<BalanceOf<T>>::default(), |acc, (_, amount)| acc + *amount);
+
+ // ensure!(total_staked >= amount, ArithmeticError::Underflow);
+
+ // <TotalStaked<T>>::set(
+ // <TotalStaked<T>>::get()
+ // .checked_sub(&amount)
+ // .ok_or(ArithmeticError::Underflow)?,
+ // );
+
+ // let block =
+ // T::RelayBlockNumberProvider::current_block_number() + T::PendingInterval::get();
+ // <PendingUnstake<T>>::insert(
+ // (&staker_id, block),
+ // <PendingUnstake<T>>::get((&staker_id, block))
+ // .checked_add(&amount)
+ // .ok_or(ArithmeticError::Overflow)?,
+ // );
+
+ // stakes.sort_by_key(|(block, _)| *block);
+
+ // let mut acc_amount = amount;
+ // let new_state = stakes
+ // .into_iter()
+ // .map_while(|(block, balance_per_block)| {
+ // if acc_amount == <BalanceOf<T>>::default() {
+ // return None;
+ // }
+ // if acc_amount <= balance_per_block {
+ // let res = (block, balance_per_block - acc_amount, acc_amount);
+ // acc_amount = <BalanceOf<T>>::default();
+ // return Some(res);
+ // } else {
+ // acc_amount -= balance_per_block;
+ // return Some((block, <BalanceOf<T>>::default(), acc_amount));
+ // }
+ // })
+ // .collect::<Vec<_>>();
+
+ // new_state
+ // .into_iter()
+ // .for_each(|(block, to_staked, _to_pending)| {
+ // if to_staked == <BalanceOf<T>>::default() {
+ // <Staked<T>>::remove((&staker_id, block));
+ // } else {
+ // <Staked<T>>::insert((&staker_id, block), to_staked);
+ // }
+ // });
+
+ // Ok(())
}
- #[pallet::weight(0)]
+ #[pallet::weight(T::WeightInfo::sponsor_collection())]
pub fn sponsor_collection(
admin: OriginFor<T>,
collection_id: CollectionId,
@@ -407,8 +481,8 @@
T::CollectionHandler::set_sponsor(Self::account_id(), collection_id)
}
- #[pallet::weight(0)]
- pub fn stop_sponsorign_collection(
+ #[pallet::weight(T::WeightInfo::stop_sponsoring_collection())]
+ pub fn stop_sponsoring_collection(
admin: OriginFor<T>,
collection_id: CollectionId,
) -> DispatchResult {
@@ -428,7 +502,7 @@
T::CollectionHandler::remove_collection_sponsor(collection_id)
}
- #[pallet::weight(0)]
+ #[pallet::weight(T::WeightInfo::sponsor_contract())]
pub fn sponsor_conract(admin: OriginFor<T>, contract_id: H160) -> DispatchResult {
let admin_id = ensure_signed(admin)?;
@@ -443,8 +517,8 @@
)
}
- #[pallet::weight(0)]
- pub fn stop_sponsorign_contract(admin: OriginFor<T>, contract_id: H160) -> DispatchResult {
+ #[pallet::weight(T::WeightInfo::stop_sponsoring_contract())]
+ pub fn stop_sponsoring_contract(admin: OriginFor<T>, contract_id: H160) -> DispatchResult {
let admin_id = ensure_signed(admin)?;
ensure!(
@@ -459,6 +533,18 @@
);
T::ContractHandler::remove_contract_sponsor(contract_id)
}
+
+ #[pallet::weight(0)]
+ pub fn payout_stakers(admin: OriginFor<T>, stakers_number: Option<u8>) -> DispatchResult {
+ let admin_id = ensure_signed(admin)?;
+
+ ensure!(
+ admin_id == Admin::<T>::get().ok_or(Error::<T>::AdminNotSet)?,
+ Error::<T>::NoPermission
+ );
+
+ Ok(())
+ }
}
}
@@ -501,7 +587,9 @@
pub fn total_staked_by_id(staker: impl EncodeLike<T::AccountId>) -> Option<BalanceOf<T>> {
let staked = Staked::<T>::iter_prefix((staker,))
.into_iter()
- .fold(<BalanceOf<T>>::default(), |acc, (_, amount)| acc + amount);
+ .fold(<BalanceOf<T>>::default(), |acc, (_, (amount, _))| {
+ acc + amount
+ });
if staked != <BalanceOf<T>>::default() {
Some(staked)
} else {
@@ -514,7 +602,7 @@
) -> Option<Vec<(T::BlockNumber, BalanceOf<T>)>> {
let mut staked = Staked::<T>::iter_prefix((staker,))
.into_iter()
- .map(|(block, amount)| (block, amount))
+ .map(|(block, (amount, _))| (block, amount))
.collect::<Vec<_>>();
staked.sort_by_key(|(block, _)| *block);
if !staked.is_empty() {
@@ -550,17 +638,17 @@
income_acc: &mut BalanceOf<T>,
) {
let income = Self::calculate_income(base);
- base.checked_add(&income).map(|res| {
- <Staked<T>>::insert((staker, block), res);
- *income_acc += income;
- <T::Currency as Currency<T::AccountId>>::transfer(
- &T::TreasuryAccountId::get(),
- staker,
- income,
- ExistenceRequirement::KeepAlive,
- )
- .and_then(|_| Self::add_lock_balance(staker, income));
- });
+ // base.checked_add(&income).map(|res| {
+ // <Staked<T>>::insert((staker, block), res);
+ // *income_acc += income;
+ // <T::Currency as Currency<T::AccountId>>::transfer(
+ // &T::TreasuryAccountId::get(),
+ // staker,
+ // income,
+ // ExistenceRequirement::KeepAlive,
+ // )
+ // .and_then(|_| Self::add_lock_balance(staker, income));
+ // });
}
fn calculate_income<I>(base: I) -> I
pallets/app-promotion/src/types.rsdiffbeforeafterboth--- a/pallets/app-promotion/src/types.rs
+++ b/pallets/app-promotion/src/types.rs
@@ -101,7 +101,7 @@
fn set_sponsor(sponsor_id: Self::AccountId, contract_id: Self::ContractId) -> DispatchResult;
- fn remove_contract_sponsor(collection_id: Self::ContractId) -> DispatchResult;
+ fn remove_contract_sponsor(contract_id: Self::ContractId) -> DispatchResult;
fn get_sponsor(contract_id: Self::ContractId)
-> Result<Option<Self::AccountId>, DispatchError>;
pallets/app-promotion/src/weights.rsdiffbeforeafterboth--- a/pallets/app-promotion/src/weights.rs
+++ b/pallets/app-promotion/src/weights.rs
@@ -3,7 +3,7 @@
//! Autogenerated weights for pallet_app_promotion
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2022-08-09, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2022-08-30, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
// Executed Command:
@@ -33,108 +33,167 @@
/// Weight functions needed for pallet_app_promotion.
pub trait WeightInfo {
- fn on_initialize() -> Weight;
fn start_app_promotion() -> Weight;
+ fn stop_app_promotion() -> Weight;
fn set_admin_address() -> Weight;
+ fn payout_stakers() -> Weight;
fn stake() -> Weight;
fn unstake() -> Weight;
fn recalculate_stake() -> Weight;
+ fn sponsor_collection() -> Weight;
+ fn stop_sponsoring_collection() -> Weight;
+ fn sponsor_contract() -> Weight;
+ fn stop_sponsoring_contract() -> Weight;
}
/// Weights for pallet_app_promotion using the Substrate node and recommended hardware.
pub struct SubstrateWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
- // Storage: Promotion PendingUnstake (r:1 w:0)
- // Storage: Promotion NextInterestBlock (r:1 w:0)
- fn on_initialize() -> Weight {
- (2_705_000 as Weight)
+ // Storage: Promotion StartBlock (r:1 w:1)
+ // Storage: ParachainSystem ValidationData (r:1 w:0)
+ // Storage: Promotion NextInterestBlock (r:0 w:1)
+ fn start_app_promotion() -> Weight {
+ (2_299_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
+ .saturating_add(T::DbWeight::get().writes(2 as Weight))
}
// Storage: Promotion StartBlock (r:1 w:1)
// Storage: Promotion NextInterestBlock (r:0 w:1)
- fn start_app_promotion() -> Weight {
- (1_436_000 as Weight)
+ fn stop_app_promotion() -> Weight {
+ (1_733_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
// Storage: Promotion Admin (r:0 w:1)
fn set_admin_address() -> Weight {
- (516_000 as Weight)
+ (553_000 as Weight)
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
+ // Storage: Promotion Admin (r:1 w:0)
+ fn payout_stakers() -> Weight {
+ (1_398_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(1 as Weight))
+ }
// Storage: System Account (r:1 w:1)
// Storage: Balances Locks (r:1 w:1)
// Storage: ParachainSystem ValidationData (r:1 w:0)
// Storage: Promotion Staked (r:1 w:1)
- // Storage: Promotion TotalStaked (r:1 w:1)
fn stake() -> Weight {
- (10_019_000 as Weight)
- .saturating_add(T::DbWeight::get().reads(5 as Weight))
- .saturating_add(T::DbWeight::get().writes(4 as Weight))
+ (9_506_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(4 as Weight))
+ .saturating_add(T::DbWeight::get().writes(3 as Weight))
}
- // Storage: System Account (r:1 w:1)
- // Storage: Balances Locks (r:1 w:1)
- // Storage: ParachainSystem ValidationData (r:1 w:0)
- // Storage: Promotion Staked (r:1 w:1)
- // Storage: Promotion TotalStaked (r:1 w:1)
+ // Storage: System Account (r:1 w:0)
fn unstake() -> Weight {
- (10_619_000 as Weight)
- .saturating_add(T::DbWeight::get().reads(5 as Weight))
- .saturating_add(T::DbWeight::get().writes(4 as Weight))
+ (2_529_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(1 as Weight))
}
- // Storage: System Account (r:2 w:0)
- // Storage: Promotion Staked (r:0 w:1)
+ // Storage: System Account (r:1 w:0)
fn recalculate_stake() -> Weight {
- (4_932_000 as Weight)
+ (2_203_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(1 as Weight))
+ }
+ // Storage: Promotion Admin (r:1 w:0)
+ // Storage: Common CollectionById (r:1 w:1)
+ fn sponsor_collection() -> Weight {
+ (10_882_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(2 as Weight))
+ .saturating_add(T::DbWeight::get().writes(1 as Weight))
+ }
+ // Storage: Promotion Admin (r:1 w:0)
+ // Storage: Common CollectionById (r:1 w:1)
+ fn stop_sponsoring_collection() -> Weight {
+ (10_544_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
+ // Storage: Promotion Admin (r:1 w:0)
+ // Storage: EvmContractHelpers Sponsoring (r:0 w:1)
+ fn sponsor_contract() -> Weight {
+ (2_163_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(1 as Weight))
+ .saturating_add(T::DbWeight::get().writes(1 as Weight))
+ }
+ // Storage: Promotion Admin (r:1 w:0)
+ // Storage: EvmContractHelpers Sponsoring (r:1 w:1)
+ fn stop_sponsoring_contract() -> Weight {
+ (3_511_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(2 as Weight))
+ .saturating_add(T::DbWeight::get().writes(1 as Weight))
+ }
}
// For backwards compatibility and tests
impl WeightInfo for () {
- // Storage: Promotion PendingUnstake (r:1 w:0)
- // Storage: Promotion NextInterestBlock (r:1 w:0)
- fn on_initialize() -> Weight {
- (2_705_000 as Weight)
+ // Storage: Promotion StartBlock (r:1 w:1)
+ // Storage: ParachainSystem ValidationData (r:1 w:0)
+ // Storage: Promotion NextInterestBlock (r:0 w:1)
+ fn start_app_promotion() -> Weight {
+ (2_299_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
// Storage: Promotion StartBlock (r:1 w:1)
// Storage: Promotion NextInterestBlock (r:0 w:1)
- fn start_app_promotion() -> Weight {
- (1_436_000 as Weight)
+ fn stop_app_promotion() -> Weight {
+ (1_733_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
// Storage: Promotion Admin (r:0 w:1)
fn set_admin_address() -> Weight {
- (516_000 as Weight)
+ (553_000 as Weight)
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
+ // Storage: Promotion Admin (r:1 w:0)
+ fn payout_stakers() -> Weight {
+ (1_398_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(1 as Weight))
+ }
// Storage: System Account (r:1 w:1)
// Storage: Balances Locks (r:1 w:1)
// Storage: ParachainSystem ValidationData (r:1 w:0)
// Storage: Promotion Staked (r:1 w:1)
- // Storage: Promotion TotalStaked (r:1 w:1)
fn stake() -> Weight {
- (10_019_000 as Weight)
- .saturating_add(RocksDbWeight::get().reads(5 as Weight))
- .saturating_add(RocksDbWeight::get().writes(4 as Weight))
+ (9_506_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(4 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
- // Storage: System Account (r:1 w:1)
- // Storage: Balances Locks (r:1 w:1)
- // Storage: ParachainSystem ValidationData (r:1 w:0)
- // Storage: Promotion Staked (r:1 w:1)
- // Storage: Promotion TotalStaked (r:1 w:1)
+ // Storage: System Account (r:1 w:0)
fn unstake() -> Weight {
- (10_619_000 as Weight)
- .saturating_add(RocksDbWeight::get().reads(5 as Weight))
- .saturating_add(RocksDbWeight::get().writes(4 as Weight))
+ (2_529_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(1 as Weight))
}
- // Storage: System Account (r:2 w:0)
- // Storage: Promotion Staked (r:0 w:1)
+ // Storage: System Account (r:1 w:0)
fn recalculate_stake() -> Weight {
- (4_932_000 as Weight)
+ (2_203_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(1 as Weight))
+ }
+ // Storage: Promotion Admin (r:1 w:0)
+ // Storage: Common CollectionById (r:1 w:1)
+ fn sponsor_collection() -> Weight {
+ (10_882_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(2 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(1 as Weight))
+ }
+ // Storage: Promotion Admin (r:1 w:0)
+ // Storage: Common CollectionById (r:1 w:1)
+ fn stop_sponsoring_collection() -> Weight {
+ (10_544_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(2 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(1 as Weight))
+ }
+ // Storage: Promotion Admin (r:1 w:0)
+ // Storage: EvmContractHelpers Sponsoring (r:0 w:1)
+ fn sponsor_contract() -> Weight {
+ (2_163_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(1 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(1 as Weight))
+ }
+ // Storage: Promotion Admin (r:1 w:0)
+ // Storage: EvmContractHelpers Sponsoring (r:1 w:1)
+ fn stop_sponsoring_contract() -> Weight {
+ (3_511_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
pallets/unique/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/unique/src/benchmarking.rs
+++ b/pallets/unique/src/benchmarking.rs
@@ -46,7 +46,9 @@
)?;
Ok(<pallet_common::CreatedCollectionCount<T>>::get())
}
-fn create_nft_collection<T: Config>(owner: T::AccountId) -> Result<CollectionId, DispatchError> {
+pub fn create_nft_collection<T: Config>(
+ owner: T::AccountId,
+) -> Result<CollectionId, DispatchError> {
create_collection_helper::<T>(owner, CollectionMode::NFT)
}
pallets/unique/src/lib.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! # Unique Pallet18//!19//! A pallet governing Unique transactions.20//!21//! - [`Config`]22//! - [`Call`]23//! - [`Pallet`]24//!25//! ## Overview26//!27//! The Unique pallet's purpose is to be the primary interface between28//! external users and the inner structure of the Unique chains.29//!30//! It also contains an implementation of [`CollectionHelpers`][`eth`],31//! an Ethereum contract dealing with collection operations.32//!33//! ## Interface34//!35//! ### Dispatchables36//!37//! - `create_collection` - Create a collection of tokens. **Deprecated**, use `create_collection_ex`.38//! - `create_collection_ex` - Create a collection of tokens with explicit parameters.39//! - `destroy_collection` - Destroy a collection if no tokens exist within.40//! - `add_to_allow_list` - Add an address to allow list.41//! - `remove_from_allow_list` - Remove an address from allow list.42//! - `change_collection_owner` - Change the owner of the collection.43//! - `add_collection_admin` - Add an admin to a collection.44//! - `remove_collection_admin` - Remove admin of a collection.45//! - `set_collection_sponsor` - Invite a new collection sponsor.46//! - `confirm_sponsorship` - Confirm own sponsorship of a collection, becoming the sponsor.47//! - `remove_collection_sponsor` - Remove a sponsor from a collection.48//! - `create_item` - Create an item within a collection.49//! - `create_multiple_items` - Create multiple items within a collection.50//! - `set_collection_properties` - Add or change collection properties.51//! - `delete_collection_properties` - Delete specified collection properties.52//! - `set_token_properties` - Add or change token properties.53//! - `delete_token_properties` - Delete token properties.54//! - `set_token_property_permissions` - Add or change token property permissions of a collection.55//! - `create_multiple_items_ex` - Create multiple items within a collection with explicitly specified initial parameters.56//! - `set_transfers_enabled_flag` - Completely allow or disallow transfers for a particular collection.57//! - `burn_item` - Destroy an item.58//! - `burn_from` - Destroy an item on behalf of the owner as a non-owner account.59//! - `transfer` - Change ownership of the token.60//! - `transfer_from` - Change ownership of the token on behalf of the owner as a non-owner account.61//! - `approve` - Allow a non-permissioned address to transfer or burn an item.62//! - `set_collection_limits` - Set specific limits of a collection.63//! - `set_collection_permissions` - Set specific permissions of a collection.64//! - `repartition` - Re-partition a refungible token, while owning all of its parts.6566#![recursion_limit = "1024"]67#![cfg_attr(not(feature = "std"), no_std)]68#![allow(69 clippy::too_many_arguments,70 clippy::unnecessary_mut_passed,71 clippy::unused_unit72)]7374extern crate alloc;7576use frame_support::{77 decl_module, decl_storage, decl_error, decl_event,78 dispatch::DispatchResult,79 ensure, fail,80 weights::{Weight},81 pallet_prelude::{DispatchResultWithPostInfo, ConstU32},82 BoundedVec,83};84use scale_info::TypeInfo;85use frame_system::{self as system, ensure_signed};86use sp_runtime::{sp_std::prelude::Vec};87use up_data_structs::{88 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,89 CreateItemData, CollectionLimits, CollectionPermissions, CollectionId, CollectionMode, TokenId,90 SponsorshipState, CreateCollectionData, CreateItemExData, budget, Property, PropertyKey,91 PropertyKeyPermission,92};93use pallet_evm::account::CrossAccountId;94use pallet_common::{95 CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_tx,96 dispatch::CollectionDispatch, RefungibleExtensionsWeightInfo,97};98pub mod eth;99100#[cfg(feature = "runtime-benchmarks")]101mod benchmarking;102pub mod weights;103use weights::WeightInfo;104105/// Maximum number of levels of depth in the token nesting tree.106pub const NESTING_BUDGET: u32 = 5;107108decl_error! {109 /// Errors for the common Unique transactions.110 pub enum Error for Module<T: Config> {111 /// Decimal_points parameter must be lower than [`up_data_structs::MAX_DECIMAL_POINTS`].112 CollectionDecimalPointLimitExceeded,113 /// This address is not set as sponsor, use setCollectionSponsor first.114 ConfirmUnsetSponsorFail,115 /// Length of items properties must be greater than 0.116 EmptyArgument,117 /// Repertition is only supported by refungible collection.118 RepartitionCalledOnNonRefungibleCollection,119 }120}121122/// Configuration trait of this pallet.123pub trait Config: system::Config + pallet_common::Config + Sized + TypeInfo {124 /// Overarching event type.125 type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;126127 /// Weight information for extrinsics in this pallet.128 type WeightInfo: WeightInfo;129130 /// Weight information for common pallet operations.131 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;132133 /// Weight info information for extra refungible pallet operations.134 type RefungibleExtensionsWeightInfo: RefungibleExtensionsWeightInfo;135}136137decl_event! {138 pub enum Event<T>139 where140 <T as frame_system::Config>::AccountId,141 <T as pallet_evm::account::Config>::CrossAccountId,142 {143 /// Collection sponsor was removed144 ///145 /// # Arguments146 /// * collection_id: ID of the affected collection.147 CollectionSponsorRemoved(CollectionId),148149 /// Collection admin was added150 ///151 /// # Arguments152 /// * collection_id: ID of the affected collection.153 /// * admin: Admin address.154 CollectionAdminAdded(CollectionId, CrossAccountId),155156 /// Collection owned was changed157 ///158 /// # Arguments159 /// * collection_id: ID of the affected collection.160 /// * owner: New owner address.161 CollectionOwnedChanged(CollectionId, AccountId),162163 /// Collection sponsor was set164 ///165 /// # Arguments166 /// * collection_id: ID of the affected collection.167 /// * owner: New sponsor address.168 CollectionSponsorSet(CollectionId, AccountId),169170 /// New sponsor was confirm171 ///172 /// # Arguments173 /// * collection_id: ID of the affected collection.174 /// * sponsor: New sponsor address.175 SponsorshipConfirmed(CollectionId, AccountId),176177 /// Collection admin was removed178 ///179 /// # Arguments180 /// * collection_id: ID of the affected collection.181 /// * admin: Removed admin address.182 CollectionAdminRemoved(CollectionId, CrossAccountId),183184 /// Address was removed from the allow list185 ///186 /// # Arguments187 /// * collection_id: ID of the affected collection.188 /// * user: Address of the removed account.189 AllowListAddressRemoved(CollectionId, CrossAccountId),190191 /// Address was added to the allow list192 ///193 /// # Arguments194 /// * collection_id: ID of the affected collection.195 /// * user: Address of the added account.196 AllowListAddressAdded(CollectionId, CrossAccountId),197198 /// Collection limits were set199 ///200 /// # Arguments201 /// * collection_id: ID of the affected collection.202 CollectionLimitSet(CollectionId),203204 /// Collection permissions were set205 ///206 /// # Arguments207 /// * collection_id: ID of the affected collection.208 CollectionPermissionSet(CollectionId),209 }210}211212type SelfWeightOf<T> = <T as Config>::WeightInfo;213214// # Used definitions215//216// ## User control levels217//218// chain-controlled - key is uncontrolled by user219// i.e autoincrementing index220// can use non-cryptographic hash221// real - key is controlled by user222// but it is hard to generate enough colliding values, i.e owner of signed txs223// can use non-cryptographic hash224// controlled - key is completly controlled by users225// i.e maps with mutable keys226// should use cryptographic hash227//228// ## User control level downgrade reasons229//230// ?1 - chain-controlled -> controlled231// collections/tokens can be destroyed, resulting in massive holes232// ?2 - chain-controlled -> controlled233// same as ?1, but can be only added, resulting in easier exploitation234// ?3 - real -> controlled235// no confirmation required, so addresses can be easily generated236decl_storage! {237 trait Store for Module<T: Config> as Unique {238239 //#region Private members240 /// Used for migrations241 ChainVersion: u64;242 //#endregion243244 //#region Tokens transfer sponosoring rate limit baskets245 /// (Collection id (controlled?2), who created (real))246 /// TODO: Off chain worker should remove from this map when collection gets removed247 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;248 /// Collection id (controlled?2), token id (controlled?2)249 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;250 /// Collection id (controlled?2), owning user (real)251 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;252 /// Collection id (controlled?2), token id (controlled?2)253 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;254 //#endregion255256 /// Variable metadata sponsoring257 /// Collection id (controlled?2), token id (controlled?2)258 #[deprecated]259 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;260 /// Last sponsoring of token property setting // todo:doc rephrase this and the following261 pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;262263 /// Last sponsoring of NFT approval in a collection264 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;265 /// Last sponsoring of fungible tokens approval in a collection266 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;267 /// Last sponsoring of RFT approval in a collection268 pub RefungibleApproveBasket get(fn refungible_approve_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;269 }270}271272decl_module! {273 /// Type alias to Pallet, to be used by construct_runtime.274 pub struct Module<T: Config> for enum Call275 where276 origin: T::Origin277 {278 type Error = Error<T>;279280 pub fn deposit_event() = default;281282 fn on_initialize(_now: T::BlockNumber) -> Weight {283 0284 }285286 fn on_runtime_upgrade() -> Weight {287 0288 }289290 /// Create a collection of tokens.291 ///292 /// Each Token may have multiple properties encoded as an array of bytes293 /// of certain length. The initial owner of the collection is set294 /// to the address that signed the transaction and can be changed later.295 ///296 /// Prefer the more advanced [`create_collection_ex`][`Pallet::create_collection_ex`] instead.297 ///298 /// # Permissions299 ///300 /// * Anyone - becomes the owner of the new collection.301 ///302 /// # Arguments303 ///304 /// * `collection_name`: Wide-character string with collection name305 /// (limit [`MAX_COLLECTION_NAME_LENGTH`]).306 /// * `collection_description`: Wide-character string with collection description307 /// (limit [`MAX_COLLECTION_DESCRIPTION_LENGTH`]).308 /// * `token_prefix`: Byte string containing the token prefix to mark a collection309 /// to which a token belongs (limit [`MAX_TOKEN_PREFIX_LENGTH`]).310 /// * `mode`: Type of items stored in the collection and type dependent data.311 // returns collection ID312 #[weight = <SelfWeightOf<T>>::create_collection()]313 #[deprecated(note = "`create_collection_ex` is more up-to-date and advanced, prefer it instead")]314 pub fn create_collection(315 origin,316 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,317 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,318 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,319 mode: CollectionMode320 ) -> DispatchResult {321 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {322 name: collection_name,323 description: collection_description,324 token_prefix,325 mode,326 ..Default::default()327 };328 Self::create_collection_ex(origin, data)329 }330331 /// Create a collection with explicit parameters.332 ///333 /// Prefer it to the deprecated [`create_collection`][`Pallet::create_collection`] method.334 ///335 /// # Permissions336 ///337 /// * Anyone - becomes the owner of the new collection.338 ///339 /// # Arguments340 ///341 /// * `data`: Explicit data of a collection used for its creation.342 #[weight = <SelfWeightOf<T>>::create_collection()]343 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {344 let sender = ensure_signed(origin)?;345346 // =========347348 let _id = T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?;349350 Ok(())351 }352353 /// Destroy a collection if no tokens exist within.354 ///355 /// # Permissions356 ///357 /// * Collection owner358 ///359 /// # Arguments360 ///361 /// * `collection_id`: Collection to destroy.362 #[weight = <SelfWeightOf<T>>::destroy_collection()]363 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {364 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);365 let collection = <CollectionHandle<T>>::try_get(collection_id)?;366 collection.check_is_internal()?;367368 // =========369370 T::CollectionDispatch::destroy(sender, collection)?;371372 // TODO: basket cleanup should be moved elsewhere373 // Maybe runtime dispatch.rs should perform it?374375 let _ = <NftTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);376 let _ = <FungibleTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);377 let _ = <ReFungibleTransferBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);378379 let _ = <NftApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);380 let _ = <FungibleApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);381 let _ = <RefungibleApproveBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);382383 Ok(())384 }385386 /// Add an address to allow list.387 ///388 /// # Permissions389 ///390 /// * Collection owner391 /// * Collection admin392 ///393 /// # Arguments394 ///395 /// * `collection_id`: ID of the modified collection.396 /// * `address`: ID of the address to be added to the allowlist.397 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]398 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{399400 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);401 let collection = <CollectionHandle<T>>::try_get(collection_id)?;402 collection.check_is_internal()?;403404 <PalletCommon<T>>::toggle_allowlist(405 &collection,406 &sender,407 &address,408 true,409 )?;410411 Self::deposit_event(Event::<T>::AllowListAddressAdded(412 collection_id,413 address414 ));415416 Ok(())417 }418419 /// Remove an address from allow list.420 ///421 /// # Permissions422 ///423 /// * Collection owner424 /// * Collection admin425 ///426 /// # Arguments427 ///428 /// * `collection_id`: ID of the modified collection.429 /// * `address`: ID of the address to be removed from the allowlist.430 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]431 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{432433 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);434 let collection = <CollectionHandle<T>>::try_get(collection_id)?;435 collection.check_is_internal()?;436437 <PalletCommon<T>>::toggle_allowlist(438 &collection,439 &sender,440 &address,441 false,442 )?;443444 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(445 collection_id,446 address447 ));448449 Ok(())450 }451452 /// Change the owner of the collection.453 ///454 /// # Permissions455 ///456 /// * Collection owner457 ///458 /// # Arguments459 ///460 /// * `collection_id`: ID of the modified collection.461 /// * `new_owner`: ID of the account that will become the owner.462 #[weight = <SelfWeightOf<T>>::change_collection_owner()]463 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {464465 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);466467 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;468 target_collection.check_is_internal()?;469 target_collection.check_is_owner(&sender)?;470471 target_collection.owner = new_owner.clone();472 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(473 collection_id,474 new_owner475 ));476477 target_collection.save()478 }479480 /// Add an admin to a collection.481 ///482 /// NFT Collection can be controlled by multiple admin addresses483 /// (some which can also be servers, for example). Admins can issue484 /// and burn NFTs, as well as add and remove other admins,485 /// but cannot change NFT or Collection ownership.486 ///487 /// # Permissions488 ///489 /// * Collection owner490 /// * Collection admin491 ///492 /// # Arguments493 ///494 /// * `collection_id`: ID of the Collection to add an admin for.495 /// * `new_admin`: Address of new admin to add.496 #[weight = <SelfWeightOf<T>>::add_collection_admin()]497 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {498 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);499 let collection = <CollectionHandle<T>>::try_get(collection_id)?;500 collection.check_is_internal()?;501502 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(503 collection_id,504 new_admin_id.clone()505 ));506507 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)508 }509510 /// Remove admin of a collection.511 ///512 /// An admin address can remove itself. List of admins may become empty,513 /// in which case only Collection Owner will be able to add an Admin.514 ///515 /// # Permissions516 ///517 /// * Collection owner518 /// * Collection admin519 ///520 /// # Arguments521 ///522 /// * `collection_id`: ID of the collection to remove the admin for.523 /// * `account_id`: Address of the admin to remove.524 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]525 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {526 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);527 let collection = <CollectionHandle<T>>::try_get(collection_id)?;528 collection.check_is_internal()?;529530 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(531 collection_id,532 account_id.clone()533 ));534535 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)536 }537538 /// Set (invite) a new collection sponsor.539 ///540 /// If successful, confirmation from the sponsor-to-be will be pending.541 ///542 /// # Permissions543 ///544 /// * Collection owner545 /// * Collection admin546 ///547 /// # Arguments548 ///549 /// * `collection_id`: ID of the modified collection.550 /// * `new_sponsor`: ID of the account of the sponsor-to-be.551 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]552 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {553 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);554555 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;556 target_collection.check_is_owner_or_admin(&sender)?;557 target_collection.check_is_internal()?;558559 target_collection.set_sponsor(new_sponsor.clone())?;560561 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(562 collection_id,563 new_sponsor564 ));565566 target_collection.save()567 }568569 /// Confirm own sponsorship of a collection, becoming the sponsor.570 ///571 /// An invitation must be pending, see [`set_collection_sponsor`][`Pallet::set_collection_sponsor`].572 /// Sponsor can pay the fees of a transaction instead of the sender,573 /// but only within specified limits.574 ///575 /// # Permissions576 ///577 /// * Sponsor-to-be578 ///579 /// # Arguments580 ///581 /// * `collection_id`: ID of the collection with the pending sponsor.582 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]583 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {584 let sender = ensure_signed(origin)?;585586 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;587 target_collection.check_is_internal()?;588 ensure!(589 target_collection.confirm_sponsorship(&sender)?,590 Error::<T>::ConfirmUnsetSponsorFail591 );592593 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(594 collection_id,595 sender596 ));597598 target_collection.save()599 }600601 /// Remove a collection's a sponsor, making everyone pay for their own transactions.602 ///603 /// # Permissions604 ///605 /// * Collection owner606 ///607 /// # Arguments608 ///609 /// * `collection_id`: ID of the collection with the sponsor to remove.610 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]611 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {612 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);613614 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;615 target_collection.check_is_internal()?;616 target_collection.check_is_owner(&sender)?;617618 target_collection.sponsorship = SponsorshipState::Disabled;619620 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(621 collection_id622 ));623 target_collection.save()624 }625626 /// Mint an item within a collection.627 ///628 /// A collection must exist first, see [`create_collection_ex`][`Pallet::create_collection_ex`].629 ///630 /// # Permissions631 ///632 /// * Collection owner633 /// * Collection admin634 /// * Anyone if635 /// * Allow List is enabled, and636 /// * Address is added to allow list, and637 /// * MintPermission is enabled (see [`set_collection_permissions`][`Pallet::set_collection_permissions`])638 ///639 /// # Arguments640 ///641 /// * `collection_id`: ID of the collection to which an item would belong.642 /// * `owner`: Address of the initial owner of the item.643 /// * `data`: Token data describing the item to store on chain.644 #[weight = T::CommonWeightInfo::create_item()]645 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {646 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);647 let budget = budget::Value::new(NESTING_BUDGET);648649 dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))650 }651652 /// Create multiple items within a collection.653 ///654 /// A collection must exist first, see [`create_collection_ex`][`Pallet::create_collection_ex`].655 ///656 /// # Permissions657 ///658 /// * Collection owner659 /// * Collection admin660 /// * Anyone if661 /// * Allow List is enabled, and662 /// * Address is added to the allow list, and663 /// * MintPermission is enabled (see [`set_collection_permissions`][`Pallet::set_collection_permissions`])664 ///665 /// # Arguments666 ///667 /// * `collection_id`: ID of the collection to which the tokens would belong.668 /// * `owner`: Address of the initial owner of the tokens.669 /// * `items_data`: Vector of data describing each item to be created.670 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]671 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {672 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);673 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);674 let budget = budget::Value::new(NESTING_BUDGET);675676 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))677 }678679 /// Add or change collection properties.680 ///681 /// # Permissions682 ///683 /// * Collection owner684 /// * Collection admin685 ///686 /// # Arguments687 ///688 /// * `collection_id`: ID of the modified collection.689 /// * `properties`: Vector of key-value pairs stored as the collection's metadata.690 /// Keys support Latin letters, `-`, `_`, and `.` as symbols.691 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]692 pub fn set_collection_properties(693 origin,694 collection_id: CollectionId,695 properties: Vec<Property>696 ) -> DispatchResultWithPostInfo {697 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);698699 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);700701 dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))702 }703704 /// Delete specified collection properties.705 ///706 /// # Permissions707 ///708 /// * Collection Owner709 /// * Collection Admin710 ///711 /// # Arguments712 ///713 /// * `collection_id`: ID of the modified collection.714 /// * `property_keys`: Vector of keys of the properties to be deleted.715 /// Keys support Latin letters, `-`, `_`, and `.` as symbols.716 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]717 pub fn delete_collection_properties(718 origin,719 collection_id: CollectionId,720 property_keys: Vec<PropertyKey>,721 ) -> DispatchResultWithPostInfo {722 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);723724 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);725726 dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))727 }728729 /// Add or change token properties according to collection's permissions.730 /// Currently properties only work with NFTs.731 ///732 /// # Permissions733 ///734 /// * Depends on collection's token property permissions and specified property mutability:735 /// * Collection owner736 /// * Collection admin737 /// * Token owner738 ///739 /// See [`set_token_property_permissions`][`Pallet::set_token_property_permissions`].740 ///741 /// # Arguments742 ///743 /// * `collection_id: ID of the collection to which the token belongs.744 /// * `token_id`: ID of the modified token.745 /// * `properties`: Vector of key-value pairs stored as the token's metadata.746 /// Keys support Latin letters, `-`, `_`, and `.` as symbols.747 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]748 pub fn set_token_properties(749 origin,750 collection_id: CollectionId,751 token_id: TokenId,752 properties: Vec<Property>753 ) -> DispatchResultWithPostInfo {754 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);755756 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);757 let budget = budget::Value::new(NESTING_BUDGET);758759 dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties, &budget))760 }761762 /// Delete specified token properties. Currently properties only work with NFTs.763 ///764 /// # Permissions765 ///766 /// * Depends on collection's token property permissions and specified property mutability:767 /// * Collection owner768 /// * Collection admin769 /// * Token owner770 ///771 /// # Arguments772 ///773 /// * `collection_id`: ID of the collection to which the token belongs.774 /// * `token_id`: ID of the modified token.775 /// * `property_keys`: Vector of keys of the properties to be deleted.776 /// Keys support Latin letters, `-`, `_`, and `.` as symbols.777 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]778 pub fn delete_token_properties(779 origin,780 collection_id: CollectionId,781 token_id: TokenId,782 property_keys: Vec<PropertyKey>783 ) -> DispatchResultWithPostInfo {784 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);785786 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);787 let budget = budget::Value::new(NESTING_BUDGET);788789 dispatch_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys, &budget))790 }791792 /// Add or change token property permissions of a collection.793 ///794 /// Without a permission for a particular key, a property with that key795 /// cannot be created in a token.796 ///797 /// # Permissions798 ///799 /// * Collection owner800 /// * Collection admin801 ///802 /// # Arguments803 ///804 /// * `collection_id`: ID of the modified collection.805 /// * `property_permissions`: Vector of permissions for property keys.806 /// Keys support Latin letters, `-`, `_`, and `.` as symbols.807 #[weight = T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32)]808 pub fn set_token_property_permissions(809 origin,810 collection_id: CollectionId,811 property_permissions: Vec<PropertyKeyPermission>,812 ) -> DispatchResultWithPostInfo {813 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);814815 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);816817 dispatch_tx::<T, _>(collection_id, |d| d.set_token_property_permissions(&sender, property_permissions))818 }819820 /// Create multiple items within a collection with explicitly specified initial parameters.821 ///822 /// # Permissions823 ///824 /// * Collection owner825 /// * Collection admin826 /// * Anyone if827 /// * Allow List is enabled, and828 /// * Address is added to allow list, and829 /// * MintPermission is enabled (see [`set_collection_permissions`][`Pallet::set_collection_permissions`])830 ///831 /// # Arguments832 ///833 /// * `collection_id`: ID of the collection to which the tokens would belong.834 /// * `data`: Explicit item creation data.835 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]836 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {837 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);838 let budget = budget::Value::new(NESTING_BUDGET);839840 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))841 }842843 /// Completely allow or disallow transfers for a particular collection.844 ///845 /// # Permissions846 ///847 /// * Collection owner848 ///849 /// # Arguments850 ///851 /// * `collection_id`: ID of the collection.852 /// * `value`: New value of the flag, are transfers allowed?853 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]854 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {855 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);856 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;857 target_collection.check_is_internal()?;858 target_collection.check_is_owner(&sender)?;859860 // =========861862 target_collection.limits.transfers_enabled = Some(value);863 target_collection.save()864 }865866 /// Destroy an item.867 ///868 /// # Permissions869 ///870 /// * Collection owner871 /// * Collection admin872 /// * Current item owner873 ///874 /// # Arguments875 ///876 /// * `collection_id`: ID of the collection to which the item belongs.877 /// * `item_id`: ID of item to burn.878 /// * `value`: Number of pieces of the item to destroy.879 /// * Non-Fungible Mode: An NFT is indivisible, there is always 1 corresponding to an ID.880 /// * Fungible Mode: The desired number of pieces to burn.881 /// * Re-Fungible Mode: The desired number of pieces to burn.882 #[weight = T::CommonWeightInfo::burn_item()]883 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {884 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);885886 let post_info = dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;887 if value == 1 {888 <NftTransferBasket<T>>::remove(collection_id, item_id);889 <NftApproveBasket<T>>::remove(collection_id, item_id);890 }891 // Those maps should be cleared only if token disappears completly, need to move this part of logic to pallets?892 // <FungibleApproveBasket<T>>::remove(collection_id, sender.as_sub());893 // <RefungibleApproveBasket<T>>::remove((collection_id, item_id, sender.as_sub()));894 Ok(post_info)895 }896897 /// Destroy a token on behalf of the owner as a non-owner account.898 ///899 /// See also: [`approve`][`Pallet::approve`].900 ///901 /// After this method executes, one approval is removed from the total so that902 /// the approved address will not be able to transfer this item again from this owner.903 ///904 /// # Permissions905 ///906 /// * Collection owner907 /// * Collection admin908 /// * Current token owner909 /// * Address approved by current item owner910 ///911 /// # Arguments912 ///913 /// * `from`: The owner of the burning item.914 /// * `collection_id`: ID of the collection to which the item belongs.915 /// * `item_id`: ID of item to burn.916 /// * `value`: Number of pieces to burn.917 /// * Non-Fungible Mode: An NFT is indivisible, there is always 1 corresponding to an ID.918 /// * Fungible Mode: The desired number of pieces to burn.919 /// * Re-Fungible Mode: The desired number of pieces to burn.920 #[weight = T::CommonWeightInfo::burn_from()]921 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {922 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);923 let budget = budget::Value::new(NESTING_BUDGET);924925 dispatch_tx::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))926 }927928 /// Change ownership of the token.929 ///930 /// # Permissions931 ///932 /// * Collection owner933 /// * Collection admin934 /// * Current token owner935 ///936 /// # Arguments937 ///938 /// * `recipient`: Address of token recipient.939 /// * `collection_id`: ID of the collection the item belongs to.940 /// * `item_id`: ID of the item.941 /// * Non-Fungible Mode: Required.942 /// * Fungible Mode: Ignored.943 /// * Re-Fungible Mode: Required.944 ///945 /// * `value`: Amount to transfer.946 /// * Non-Fungible Mode: An NFT is indivisible, there is always 1 corresponding to an ID.947 /// * Fungible Mode: The desired number of pieces to transfer.948 /// * Re-Fungible Mode: The desired number of pieces to transfer.949 #[weight = T::CommonWeightInfo::transfer()]950 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {951 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);952 let budget = budget::Value::new(NESTING_BUDGET);953954 dispatch_tx::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))955 }956957 /// Allow a non-permissioned address to transfer or burn an item.958 ///959 /// # Permissions960 ///961 /// * Collection owner962 /// * Collection admin963 /// * Current item owner964 ///965 /// # Arguments966 ///967 /// * `spender`: Account to be approved to make specific transactions on non-owned tokens.968 /// * `collection_id`: ID of the collection the item belongs to.969 /// * `item_id`: ID of the item transactions on which are now approved.970 /// * `amount`: Number of pieces of the item approved for a transaction (maximum of 1 for NFTs).971 /// Set to 0 to revoke the approval.972 #[weight = T::CommonWeightInfo::approve()]973 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {974 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);975976 dispatch_tx::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))977 }978979 /// Change ownership of an item on behalf of the owner as a non-owner account.980 ///981 /// See the [`approve`][`Pallet::approve`] method for additional information.982 ///983 /// After this method executes, one approval is removed from the total so that984 /// the approved address will not be able to transfer this item again from this owner.985 ///986 /// # Permissions987 ///988 /// * Collection owner989 /// * Collection admin990 /// * Current item owner991 /// * Address approved by current item owner992 ///993 /// # Arguments994 ///995 /// * `from`: Address that currently owns the token.996 /// * `recipient`: Address of the new token-owner-to-be.997 /// * `collection_id`: ID of the collection the item.998 /// * `item_id`: ID of the item to be transferred.999 /// * `value`: Amount to transfer.1000 /// * Non-Fungible Mode: An NFT is indivisible, there is always 1 corresponding to an ID.1001 /// * Fungible Mode: The desired number of pieces to transfer.1002 /// * Re-Fungible Mode: The desired number of pieces to transfer.1003 #[weight = T::CommonWeightInfo::transfer_from()]1004 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {1005 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1006 let budget = budget::Value::new(NESTING_BUDGET);10071008 dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))1009 }10101011 /// Set specific limits of a collection. Empty, or None fields mean chain default.1012 ///1013 /// # Permissions1014 ///1015 /// * Collection owner1016 /// * Collection admin1017 ///1018 /// # Arguments1019 ///1020 /// * `collection_id`: ID of the modified collection.1021 /// * `new_limit`: New limits of the collection. Fields that are not set (None)1022 /// will not overwrite the old ones.1023 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1024 pub fn set_collection_limits(1025 origin,1026 collection_id: CollectionId,1027 new_limit: CollectionLimits,1028 ) -> DispatchResult {1029 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1030 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1031 target_collection.check_is_internal()?;1032 target_collection.check_is_owner_or_admin(&sender)?;1033 let old_limit = &target_collection.limits;10341035 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;10361037 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1038 collection_id1039 ));10401041 target_collection.save()1042 }10431044 /// Set specific permissions of a collection. Empty, or None fields mean chain default.1045 ///1046 /// # Permissions1047 ///1048 /// * Collection owner1049 /// * Collection admin1050 ///1051 /// # Arguments1052 ///1053 /// * `collection_id`: ID of the modified collection.1054 /// * `new_permission`: New permissions of the collection. Fields that are not set (None)1055 /// will not overwrite the old ones.1056 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1057 pub fn set_collection_permissions(1058 origin,1059 collection_id: CollectionId,1060 new_permission: CollectionPermissions,1061 ) -> DispatchResult {1062 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1063 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1064 target_collection.check_is_internal()?;1065 target_collection.check_is_owner_or_admin(&sender)?;1066 let old_limit = &target_collection.permissions;10671068 target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_permission)?;10691070 <Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(1071 collection_id1072 ));10731074 target_collection.save()1075 }10761077 /// Re-partition a refungible token, while owning all of its parts/pieces.1078 ///1079 /// # Permissions1080 ///1081 /// * Token owner (must own every part)1082 ///1083 /// # Arguments1084 ///1085 /// * `collection_id`: ID of the collection the RFT belongs to.1086 /// * `token_id`: ID of the RFT.1087 /// * `amount`: New number of parts/pieces into which the token shall be partitioned.1088 #[weight = T::RefungibleExtensionsWeightInfo::repartition()]1089 pub fn repartition(1090 origin,1091 collection_id: CollectionId,1092 token_id: TokenId,1093 amount: u128,1094 ) -> DispatchResultWithPostInfo {1095 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1096 dispatch_tx::<T, _>(collection_id, |d| {1097 if let Some(refungible_extensions) = d.refungible_extensions() {1098 refungible_extensions.repartition(&sender, token_id, amount)1099 } else {1100 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)1101 }1102 })1103 }1104 }1105}1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! # Unique Pallet18//!19//! A pallet governing Unique transactions.20//!21//! - [`Config`]22//! - [`Call`]23//! - [`Pallet`]24//!25//! ## Overview26//!27//! The Unique pallet's purpose is to be the primary interface between28//! external users and the inner structure of the Unique chains.29//!30//! It also contains an implementation of [`CollectionHelpers`][`eth`],31//! an Ethereum contract dealing with collection operations.32//!33//! ## Interface34//!35//! ### Dispatchables36//!37//! - `create_collection` - Create a collection of tokens. **Deprecated**, use `create_collection_ex`.38//! - `create_collection_ex` - Create a collection of tokens with explicit parameters.39//! - `destroy_collection` - Destroy a collection if no tokens exist within.40//! - `add_to_allow_list` - Add an address to allow list.41//! - `remove_from_allow_list` - Remove an address from allow list.42//! - `change_collection_owner` - Change the owner of the collection.43//! - `add_collection_admin` - Add an admin to a collection.44//! - `remove_collection_admin` - Remove admin of a collection.45//! - `set_collection_sponsor` - Invite a new collection sponsor.46//! - `confirm_sponsorship` - Confirm own sponsorship of a collection, becoming the sponsor.47//! - `remove_collection_sponsor` - Remove a sponsor from a collection.48//! - `create_item` - Create an item within a collection.49//! - `create_multiple_items` - Create multiple items within a collection.50//! - `set_collection_properties` - Add or change collection properties.51//! - `delete_collection_properties` - Delete specified collection properties.52//! - `set_token_properties` - Add or change token properties.53//! - `delete_token_properties` - Delete token properties.54//! - `set_token_property_permissions` - Add or change token property permissions of a collection.55//! - `create_multiple_items_ex` - Create multiple items within a collection with explicitly specified initial parameters.56//! - `set_transfers_enabled_flag` - Completely allow or disallow transfers for a particular collection.57//! - `burn_item` - Destroy an item.58//! - `burn_from` - Destroy an item on behalf of the owner as a non-owner account.59//! - `transfer` - Change ownership of the token.60//! - `transfer_from` - Change ownership of the token on behalf of the owner as a non-owner account.61//! - `approve` - Allow a non-permissioned address to transfer or burn an item.62//! - `set_collection_limits` - Set specific limits of a collection.63//! - `set_collection_permissions` - Set specific permissions of a collection.64//! - `repartition` - Re-partition a refungible token, while owning all of its parts.6566#![recursion_limit = "1024"]67#![cfg_attr(not(feature = "std"), no_std)]68#![allow(69 clippy::too_many_arguments,70 clippy::unnecessary_mut_passed,71 clippy::unused_unit72)]7374extern crate alloc;7576use frame_support::{77 decl_module, decl_storage, decl_error, decl_event,78 dispatch::DispatchResult,79 ensure, fail,80 weights::{Weight},81 pallet_prelude::{DispatchResultWithPostInfo, ConstU32},82 BoundedVec,83};84use scale_info::TypeInfo;85use frame_system::{self as system, ensure_signed};86use sp_runtime::{sp_std::prelude::Vec};87use up_data_structs::{88 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,89 CreateItemData, CollectionLimits, CollectionPermissions, CollectionId, CollectionMode, TokenId,90 SponsorshipState, CreateCollectionData, CreateItemExData, budget, Property, PropertyKey,91 PropertyKeyPermission,92};93use pallet_evm::account::CrossAccountId;94use pallet_common::{95 CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_tx,96 dispatch::CollectionDispatch, RefungibleExtensionsWeightInfo,97};98pub mod eth;99100#[cfg(feature = "runtime-benchmarks")]101pub mod benchmarking;102pub mod weights;103use weights::WeightInfo;104105/// Maximum number of levels of depth in the token nesting tree.106pub const NESTING_BUDGET: u32 = 5;107108decl_error! {109 /// Errors for the common Unique transactions.110 pub enum Error for Module<T: Config> {111 /// Decimal_points parameter must be lower than [`up_data_structs::MAX_DECIMAL_POINTS`].112 CollectionDecimalPointLimitExceeded,113 /// This address is not set as sponsor, use setCollectionSponsor first.114 ConfirmUnsetSponsorFail,115 /// Length of items properties must be greater than 0.116 EmptyArgument,117 /// Repertition is only supported by refungible collection.118 RepartitionCalledOnNonRefungibleCollection,119 }120}121122/// Configuration trait of this pallet.123pub trait Config: system::Config + pallet_common::Config + Sized + TypeInfo {124 /// Overarching event type.125 type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;126127 /// Weight information for extrinsics in this pallet.128 type WeightInfo: WeightInfo;129130 /// Weight information for common pallet operations.131 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;132133 /// Weight info information for extra refungible pallet operations.134 type RefungibleExtensionsWeightInfo: RefungibleExtensionsWeightInfo;135}136137decl_event! {138 pub enum Event<T>139 where140 <T as frame_system::Config>::AccountId,141 <T as pallet_evm::account::Config>::CrossAccountId,142 {143 /// Collection sponsor was removed144 ///145 /// # Arguments146 /// * collection_id: ID of the affected collection.147 CollectionSponsorRemoved(CollectionId),148149 /// Collection admin was added150 ///151 /// # Arguments152 /// * collection_id: ID of the affected collection.153 /// * admin: Admin address.154 CollectionAdminAdded(CollectionId, CrossAccountId),155156 /// Collection owned was changed157 ///158 /// # Arguments159 /// * collection_id: ID of the affected collection.160 /// * owner: New owner address.161 CollectionOwnedChanged(CollectionId, AccountId),162163 /// Collection sponsor was set164 ///165 /// # Arguments166 /// * collection_id: ID of the affected collection.167 /// * owner: New sponsor address.168 CollectionSponsorSet(CollectionId, AccountId),169170 /// New sponsor was confirm171 ///172 /// # Arguments173 /// * collection_id: ID of the affected collection.174 /// * sponsor: New sponsor address.175 SponsorshipConfirmed(CollectionId, AccountId),176177 /// Collection admin was removed178 ///179 /// # Arguments180 /// * collection_id: ID of the affected collection.181 /// * admin: Removed admin address.182 CollectionAdminRemoved(CollectionId, CrossAccountId),183184 /// Address was removed from the allow list185 ///186 /// # Arguments187 /// * collection_id: ID of the affected collection.188 /// * user: Address of the removed account.189 AllowListAddressRemoved(CollectionId, CrossAccountId),190191 /// Address was added to the allow list192 ///193 /// # Arguments194 /// * collection_id: ID of the affected collection.195 /// * user: Address of the added account.196 AllowListAddressAdded(CollectionId, CrossAccountId),197198 /// Collection limits were set199 ///200 /// # Arguments201 /// * collection_id: ID of the affected collection.202 CollectionLimitSet(CollectionId),203204 /// Collection permissions were set205 ///206 /// # Arguments207 /// * collection_id: ID of the affected collection.208 CollectionPermissionSet(CollectionId),209 }210}211212type SelfWeightOf<T> = <T as Config>::WeightInfo;213214// # Used definitions215//216// ## User control levels217//218// chain-controlled - key is uncontrolled by user219// i.e autoincrementing index220// can use non-cryptographic hash221// real - key is controlled by user222// but it is hard to generate enough colliding values, i.e owner of signed txs223// can use non-cryptographic hash224// controlled - key is completly controlled by users225// i.e maps with mutable keys226// should use cryptographic hash227//228// ## User control level downgrade reasons229//230// ?1 - chain-controlled -> controlled231// collections/tokens can be destroyed, resulting in massive holes232// ?2 - chain-controlled -> controlled233// same as ?1, but can be only added, resulting in easier exploitation234// ?3 - real -> controlled235// no confirmation required, so addresses can be easily generated236decl_storage! {237 trait Store for Module<T: Config> as Unique {238239 //#region Private members240 /// Used for migrations241 ChainVersion: u64;242 //#endregion243244 //#region Tokens transfer sponosoring rate limit baskets245 /// (Collection id (controlled?2), who created (real))246 /// TODO: Off chain worker should remove from this map when collection gets removed247 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;248 /// Collection id (controlled?2), token id (controlled?2)249 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;250 /// Collection id (controlled?2), owning user (real)251 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;252 /// Collection id (controlled?2), token id (controlled?2)253 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;254 //#endregion255256 /// Variable metadata sponsoring257 /// Collection id (controlled?2), token id (controlled?2)258 #[deprecated]259 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;260 /// Last sponsoring of token property setting // todo:doc rephrase this and the following261 pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;262263 /// Last sponsoring of NFT approval in a collection264 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;265 /// Last sponsoring of fungible tokens approval in a collection266 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;267 /// Last sponsoring of RFT approval in a collection268 pub RefungibleApproveBasket get(fn refungible_approve_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;269 }270}271272decl_module! {273 /// Type alias to Pallet, to be used by construct_runtime.274 pub struct Module<T: Config> for enum Call275 where276 origin: T::Origin277 {278 type Error = Error<T>;279280 pub fn deposit_event() = default;281282 fn on_initialize(_now: T::BlockNumber) -> Weight {283 0284 }285286 fn on_runtime_upgrade() -> Weight {287 0288 }289290 /// Create a collection of tokens.291 ///292 /// Each Token may have multiple properties encoded as an array of bytes293 /// of certain length. The initial owner of the collection is set294 /// to the address that signed the transaction and can be changed later.295 ///296 /// Prefer the more advanced [`create_collection_ex`][`Pallet::create_collection_ex`] instead.297 ///298 /// # Permissions299 ///300 /// * Anyone - becomes the owner of the new collection.301 ///302 /// # Arguments303 ///304 /// * `collection_name`: Wide-character string with collection name305 /// (limit [`MAX_COLLECTION_NAME_LENGTH`]).306 /// * `collection_description`: Wide-character string with collection description307 /// (limit [`MAX_COLLECTION_DESCRIPTION_LENGTH`]).308 /// * `token_prefix`: Byte string containing the token prefix to mark a collection309 /// to which a token belongs (limit [`MAX_TOKEN_PREFIX_LENGTH`]).310 /// * `mode`: Type of items stored in the collection and type dependent data.311 // returns collection ID312 #[weight = <SelfWeightOf<T>>::create_collection()]313 #[deprecated(note = "`create_collection_ex` is more up-to-date and advanced, prefer it instead")]314 pub fn create_collection(315 origin,316 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,317 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,318 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,319 mode: CollectionMode320 ) -> DispatchResult {321 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {322 name: collection_name,323 description: collection_description,324 token_prefix,325 mode,326 ..Default::default()327 };328 Self::create_collection_ex(origin, data)329 }330331 /// Create a collection with explicit parameters.332 ///333 /// Prefer it to the deprecated [`create_collection`][`Pallet::create_collection`] method.334 ///335 /// # Permissions336 ///337 /// * Anyone - becomes the owner of the new collection.338 ///339 /// # Arguments340 ///341 /// * `data`: Explicit data of a collection used for its creation.342 #[weight = <SelfWeightOf<T>>::create_collection()]343 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {344 let sender = ensure_signed(origin)?;345346 // =========347348 let _id = T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?;349350 Ok(())351 }352353 /// Destroy a collection if no tokens exist within.354 ///355 /// # Permissions356 ///357 /// * Collection owner358 ///359 /// # Arguments360 ///361 /// * `collection_id`: Collection to destroy.362 #[weight = <SelfWeightOf<T>>::destroy_collection()]363 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {364 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);365 let collection = <CollectionHandle<T>>::try_get(collection_id)?;366 collection.check_is_internal()?;367368 // =========369370 T::CollectionDispatch::destroy(sender, collection)?;371372 // TODO: basket cleanup should be moved elsewhere373 // Maybe runtime dispatch.rs should perform it?374375 let _ = <NftTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);376 let _ = <FungibleTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);377 let _ = <ReFungibleTransferBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);378379 let _ = <NftApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);380 let _ = <FungibleApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);381 let _ = <RefungibleApproveBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);382383 Ok(())384 }385386 /// Add an address to allow list.387 ///388 /// # Permissions389 ///390 /// * Collection owner391 /// * Collection admin392 ///393 /// # Arguments394 ///395 /// * `collection_id`: ID of the modified collection.396 /// * `address`: ID of the address to be added to the allowlist.397 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]398 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{399400 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);401 let collection = <CollectionHandle<T>>::try_get(collection_id)?;402 collection.check_is_internal()?;403404 <PalletCommon<T>>::toggle_allowlist(405 &collection,406 &sender,407 &address,408 true,409 )?;410411 Self::deposit_event(Event::<T>::AllowListAddressAdded(412 collection_id,413 address414 ));415416 Ok(())417 }418419 /// Remove an address from allow list.420 ///421 /// # Permissions422 ///423 /// * Collection owner424 /// * Collection admin425 ///426 /// # Arguments427 ///428 /// * `collection_id`: ID of the modified collection.429 /// * `address`: ID of the address to be removed from the allowlist.430 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]431 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{432433 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);434 let collection = <CollectionHandle<T>>::try_get(collection_id)?;435 collection.check_is_internal()?;436437 <PalletCommon<T>>::toggle_allowlist(438 &collection,439 &sender,440 &address,441 false,442 )?;443444 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(445 collection_id,446 address447 ));448449 Ok(())450 }451452 /// Change the owner of the collection.453 ///454 /// # Permissions455 ///456 /// * Collection owner457 ///458 /// # Arguments459 ///460 /// * `collection_id`: ID of the modified collection.461 /// * `new_owner`: ID of the account that will become the owner.462 #[weight = <SelfWeightOf<T>>::change_collection_owner()]463 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {464465 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);466467 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;468 target_collection.check_is_internal()?;469 target_collection.check_is_owner(&sender)?;470471 target_collection.owner = new_owner.clone();472 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(473 collection_id,474 new_owner475 ));476477 target_collection.save()478 }479480 /// Add an admin to a collection.481 ///482 /// NFT Collection can be controlled by multiple admin addresses483 /// (some which can also be servers, for example). Admins can issue484 /// and burn NFTs, as well as add and remove other admins,485 /// but cannot change NFT or Collection ownership.486 ///487 /// # Permissions488 ///489 /// * Collection owner490 /// * Collection admin491 ///492 /// # Arguments493 ///494 /// * `collection_id`: ID of the Collection to add an admin for.495 /// * `new_admin`: Address of new admin to add.496 #[weight = <SelfWeightOf<T>>::add_collection_admin()]497 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {498 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);499 let collection = <CollectionHandle<T>>::try_get(collection_id)?;500 collection.check_is_internal()?;501502 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(503 collection_id,504 new_admin_id.clone()505 ));506507 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)508 }509510 /// Remove admin of a collection.511 ///512 /// An admin address can remove itself. List of admins may become empty,513 /// in which case only Collection Owner will be able to add an Admin.514 ///515 /// # Permissions516 ///517 /// * Collection owner518 /// * Collection admin519 ///520 /// # Arguments521 ///522 /// * `collection_id`: ID of the collection to remove the admin for.523 /// * `account_id`: Address of the admin to remove.524 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]525 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {526 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);527 let collection = <CollectionHandle<T>>::try_get(collection_id)?;528 collection.check_is_internal()?;529530 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(531 collection_id,532 account_id.clone()533 ));534535 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)536 }537538 /// Set (invite) a new collection sponsor.539 ///540 /// If successful, confirmation from the sponsor-to-be will be pending.541 ///542 /// # Permissions543 ///544 /// * Collection owner545 /// * Collection admin546 ///547 /// # Arguments548 ///549 /// * `collection_id`: ID of the modified collection.550 /// * `new_sponsor`: ID of the account of the sponsor-to-be.551 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]552 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {553 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);554555 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;556 target_collection.check_is_owner_or_admin(&sender)?;557 target_collection.check_is_internal()?;558559 target_collection.set_sponsor(new_sponsor.clone())?;560561 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(562 collection_id,563 new_sponsor564 ));565566 target_collection.save()567 }568569 /// Confirm own sponsorship of a collection, becoming the sponsor.570 ///571 /// An invitation must be pending, see [`set_collection_sponsor`][`Pallet::set_collection_sponsor`].572 /// Sponsor can pay the fees of a transaction instead of the sender,573 /// but only within specified limits.574 ///575 /// # Permissions576 ///577 /// * Sponsor-to-be578 ///579 /// # Arguments580 ///581 /// * `collection_id`: ID of the collection with the pending sponsor.582 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]583 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {584 let sender = ensure_signed(origin)?;585586 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;587 target_collection.check_is_internal()?;588 ensure!(589 target_collection.confirm_sponsorship(&sender)?,590 Error::<T>::ConfirmUnsetSponsorFail591 );592593 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(594 collection_id,595 sender596 ));597598 target_collection.save()599 }600601 /// Remove a collection's a sponsor, making everyone pay for their own transactions.602 ///603 /// # Permissions604 ///605 /// * Collection owner606 ///607 /// # Arguments608 ///609 /// * `collection_id`: ID of the collection with the sponsor to remove.610 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]611 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {612 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);613614 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;615 target_collection.check_is_internal()?;616 target_collection.check_is_owner(&sender)?;617618 target_collection.sponsorship = SponsorshipState::Disabled;619620 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(621 collection_id622 ));623 target_collection.save()624 }625626 /// Mint an item within a collection.627 ///628 /// A collection must exist first, see [`create_collection_ex`][`Pallet::create_collection_ex`].629 ///630 /// # Permissions631 ///632 /// * Collection owner633 /// * Collection admin634 /// * Anyone if635 /// * Allow List is enabled, and636 /// * Address is added to allow list, and637 /// * MintPermission is enabled (see [`set_collection_permissions`][`Pallet::set_collection_permissions`])638 ///639 /// # Arguments640 ///641 /// * `collection_id`: ID of the collection to which an item would belong.642 /// * `owner`: Address of the initial owner of the item.643 /// * `data`: Token data describing the item to store on chain.644 #[weight = T::CommonWeightInfo::create_item()]645 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {646 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);647 let budget = budget::Value::new(NESTING_BUDGET);648649 dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))650 }651652 /// Create multiple items within a collection.653 ///654 /// A collection must exist first, see [`create_collection_ex`][`Pallet::create_collection_ex`].655 ///656 /// # Permissions657 ///658 /// * Collection owner659 /// * Collection admin660 /// * Anyone if661 /// * Allow List is enabled, and662 /// * Address is added to the allow list, and663 /// * MintPermission is enabled (see [`set_collection_permissions`][`Pallet::set_collection_permissions`])664 ///665 /// # Arguments666 ///667 /// * `collection_id`: ID of the collection to which the tokens would belong.668 /// * `owner`: Address of the initial owner of the tokens.669 /// * `items_data`: Vector of data describing each item to be created.670 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]671 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {672 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);673 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);674 let budget = budget::Value::new(NESTING_BUDGET);675676 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))677 }678679 /// Add or change collection properties.680 ///681 /// # Permissions682 ///683 /// * Collection owner684 /// * Collection admin685 ///686 /// # Arguments687 ///688 /// * `collection_id`: ID of the modified collection.689 /// * `properties`: Vector of key-value pairs stored as the collection's metadata.690 /// Keys support Latin letters, `-`, `_`, and `.` as symbols.691 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]692 pub fn set_collection_properties(693 origin,694 collection_id: CollectionId,695 properties: Vec<Property>696 ) -> DispatchResultWithPostInfo {697 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);698699 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);700701 dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))702 }703704 /// Delete specified collection properties.705 ///706 /// # Permissions707 ///708 /// * Collection Owner709 /// * Collection Admin710 ///711 /// # Arguments712 ///713 /// * `collection_id`: ID of the modified collection.714 /// * `property_keys`: Vector of keys of the properties to be deleted.715 /// Keys support Latin letters, `-`, `_`, and `.` as symbols.716 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]717 pub fn delete_collection_properties(718 origin,719 collection_id: CollectionId,720 property_keys: Vec<PropertyKey>,721 ) -> DispatchResultWithPostInfo {722 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);723724 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);725726 dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))727 }728729 /// Add or change token properties according to collection's permissions.730 /// Currently properties only work with NFTs.731 ///732 /// # Permissions733 ///734 /// * Depends on collection's token property permissions and specified property mutability:735 /// * Collection owner736 /// * Collection admin737 /// * Token owner738 ///739 /// See [`set_token_property_permissions`][`Pallet::set_token_property_permissions`].740 ///741 /// # Arguments742 ///743 /// * `collection_id: ID of the collection to which the token belongs.744 /// * `token_id`: ID of the modified token.745 /// * `properties`: Vector of key-value pairs stored as the token's metadata.746 /// Keys support Latin letters, `-`, `_`, and `.` as symbols.747 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]748 pub fn set_token_properties(749 origin,750 collection_id: CollectionId,751 token_id: TokenId,752 properties: Vec<Property>753 ) -> DispatchResultWithPostInfo {754 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);755756 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);757 let budget = budget::Value::new(NESTING_BUDGET);758759 dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties, &budget))760 }761762 /// Delete specified token properties. Currently properties only work with NFTs.763 ///764 /// # Permissions765 ///766 /// * Depends on collection's token property permissions and specified property mutability:767 /// * Collection owner768 /// * Collection admin769 /// * Token owner770 ///771 /// # Arguments772 ///773 /// * `collection_id`: ID of the collection to which the token belongs.774 /// * `token_id`: ID of the modified token.775 /// * `property_keys`: Vector of keys of the properties to be deleted.776 /// Keys support Latin letters, `-`, `_`, and `.` as symbols.777 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]778 pub fn delete_token_properties(779 origin,780 collection_id: CollectionId,781 token_id: TokenId,782 property_keys: Vec<PropertyKey>783 ) -> DispatchResultWithPostInfo {784 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);785786 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);787 let budget = budget::Value::new(NESTING_BUDGET);788789 dispatch_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys, &budget))790 }791792 /// Add or change token property permissions of a collection.793 ///794 /// Without a permission for a particular key, a property with that key795 /// cannot be created in a token.796 ///797 /// # Permissions798 ///799 /// * Collection owner800 /// * Collection admin801 ///802 /// # Arguments803 ///804 /// * `collection_id`: ID of the modified collection.805 /// * `property_permissions`: Vector of permissions for property keys.806 /// Keys support Latin letters, `-`, `_`, and `.` as symbols.807 #[weight = T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32)]808 pub fn set_token_property_permissions(809 origin,810 collection_id: CollectionId,811 property_permissions: Vec<PropertyKeyPermission>,812 ) -> DispatchResultWithPostInfo {813 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);814815 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);816817 dispatch_tx::<T, _>(collection_id, |d| d.set_token_property_permissions(&sender, property_permissions))818 }819820 /// Create multiple items within a collection with explicitly specified initial parameters.821 ///822 /// # Permissions823 ///824 /// * Collection owner825 /// * Collection admin826 /// * Anyone if827 /// * Allow List is enabled, and828 /// * Address is added to allow list, and829 /// * MintPermission is enabled (see [`set_collection_permissions`][`Pallet::set_collection_permissions`])830 ///831 /// # Arguments832 ///833 /// * `collection_id`: ID of the collection to which the tokens would belong.834 /// * `data`: Explicit item creation data.835 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]836 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {837 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);838 let budget = budget::Value::new(NESTING_BUDGET);839840 dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))841 }842843 /// Completely allow or disallow transfers for a particular collection.844 ///845 /// # Permissions846 ///847 /// * Collection owner848 ///849 /// # Arguments850 ///851 /// * `collection_id`: ID of the collection.852 /// * `value`: New value of the flag, are transfers allowed?853 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]854 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {855 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);856 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;857 target_collection.check_is_internal()?;858 target_collection.check_is_owner(&sender)?;859860 // =========861862 target_collection.limits.transfers_enabled = Some(value);863 target_collection.save()864 }865866 /// Destroy an item.867 ///868 /// # Permissions869 ///870 /// * Collection owner871 /// * Collection admin872 /// * Current item owner873 ///874 /// # Arguments875 ///876 /// * `collection_id`: ID of the collection to which the item belongs.877 /// * `item_id`: ID of item to burn.878 /// * `value`: Number of pieces of the item to destroy.879 /// * Non-Fungible Mode: An NFT is indivisible, there is always 1 corresponding to an ID.880 /// * Fungible Mode: The desired number of pieces to burn.881 /// * Re-Fungible Mode: The desired number of pieces to burn.882 #[weight = T::CommonWeightInfo::burn_item()]883 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {884 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);885886 let post_info = dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;887 if value == 1 {888 <NftTransferBasket<T>>::remove(collection_id, item_id);889 <NftApproveBasket<T>>::remove(collection_id, item_id);890 }891 // Those maps should be cleared only if token disappears completly, need to move this part of logic to pallets?892 // <FungibleApproveBasket<T>>::remove(collection_id, sender.as_sub());893 // <RefungibleApproveBasket<T>>::remove((collection_id, item_id, sender.as_sub()));894 Ok(post_info)895 }896897 /// Destroy a token on behalf of the owner as a non-owner account.898 ///899 /// See also: [`approve`][`Pallet::approve`].900 ///901 /// After this method executes, one approval is removed from the total so that902 /// the approved address will not be able to transfer this item again from this owner.903 ///904 /// # Permissions905 ///906 /// * Collection owner907 /// * Collection admin908 /// * Current token owner909 /// * Address approved by current item owner910 ///911 /// # Arguments912 ///913 /// * `from`: The owner of the burning item.914 /// * `collection_id`: ID of the collection to which the item belongs.915 /// * `item_id`: ID of item to burn.916 /// * `value`: Number of pieces to burn.917 /// * Non-Fungible Mode: An NFT is indivisible, there is always 1 corresponding to an ID.918 /// * Fungible Mode: The desired number of pieces to burn.919 /// * Re-Fungible Mode: The desired number of pieces to burn.920 #[weight = T::CommonWeightInfo::burn_from()]921 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {922 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);923 let budget = budget::Value::new(NESTING_BUDGET);924925 dispatch_tx::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))926 }927928 /// Change ownership of the token.929 ///930 /// # Permissions931 ///932 /// * Collection owner933 /// * Collection admin934 /// * Current token owner935 ///936 /// # Arguments937 ///938 /// * `recipient`: Address of token recipient.939 /// * `collection_id`: ID of the collection the item belongs to.940 /// * `item_id`: ID of the item.941 /// * Non-Fungible Mode: Required.942 /// * Fungible Mode: Ignored.943 /// * Re-Fungible Mode: Required.944 ///945 /// * `value`: Amount to transfer.946 /// * Non-Fungible Mode: An NFT is indivisible, there is always 1 corresponding to an ID.947 /// * Fungible Mode: The desired number of pieces to transfer.948 /// * Re-Fungible Mode: The desired number of pieces to transfer.949 #[weight = T::CommonWeightInfo::transfer()]950 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {951 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);952 let budget = budget::Value::new(NESTING_BUDGET);953954 dispatch_tx::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))955 }956957 /// Allow a non-permissioned address to transfer or burn an item.958 ///959 /// # Permissions960 ///961 /// * Collection owner962 /// * Collection admin963 /// * Current item owner964 ///965 /// # Arguments966 ///967 /// * `spender`: Account to be approved to make specific transactions on non-owned tokens.968 /// * `collection_id`: ID of the collection the item belongs to.969 /// * `item_id`: ID of the item transactions on which are now approved.970 /// * `amount`: Number of pieces of the item approved for a transaction (maximum of 1 for NFTs).971 /// Set to 0 to revoke the approval.972 #[weight = T::CommonWeightInfo::approve()]973 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {974 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);975976 dispatch_tx::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))977 }978979 /// Change ownership of an item on behalf of the owner as a non-owner account.980 ///981 /// See the [`approve`][`Pallet::approve`] method for additional information.982 ///983 /// After this method executes, one approval is removed from the total so that984 /// the approved address will not be able to transfer this item again from this owner.985 ///986 /// # Permissions987 ///988 /// * Collection owner989 /// * Collection admin990 /// * Current item owner991 /// * Address approved by current item owner992 ///993 /// # Arguments994 ///995 /// * `from`: Address that currently owns the token.996 /// * `recipient`: Address of the new token-owner-to-be.997 /// * `collection_id`: ID of the collection the item.998 /// * `item_id`: ID of the item to be transferred.999 /// * `value`: Amount to transfer.1000 /// * Non-Fungible Mode: An NFT is indivisible, there is always 1 corresponding to an ID.1001 /// * Fungible Mode: The desired number of pieces to transfer.1002 /// * Re-Fungible Mode: The desired number of pieces to transfer.1003 #[weight = T::CommonWeightInfo::transfer_from()]1004 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {1005 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1006 let budget = budget::Value::new(NESTING_BUDGET);10071008 dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))1009 }10101011 /// Set specific limits of a collection. Empty, or None fields mean chain default.1012 ///1013 /// # Permissions1014 ///1015 /// * Collection owner1016 /// * Collection admin1017 ///1018 /// # Arguments1019 ///1020 /// * `collection_id`: ID of the modified collection.1021 /// * `new_limit`: New limits of the collection. Fields that are not set (None)1022 /// will not overwrite the old ones.1023 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1024 pub fn set_collection_limits(1025 origin,1026 collection_id: CollectionId,1027 new_limit: CollectionLimits,1028 ) -> DispatchResult {1029 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1030 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1031 target_collection.check_is_internal()?;1032 target_collection.check_is_owner_or_admin(&sender)?;1033 let old_limit = &target_collection.limits;10341035 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;10361037 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1038 collection_id1039 ));10401041 target_collection.save()1042 }10431044 /// Set specific permissions of a collection. Empty, or None fields mean chain default.1045 ///1046 /// # Permissions1047 ///1048 /// * Collection owner1049 /// * Collection admin1050 ///1051 /// # Arguments1052 ///1053 /// * `collection_id`: ID of the modified collection.1054 /// * `new_permission`: New permissions of the collection. Fields that are not set (None)1055 /// will not overwrite the old ones.1056 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1057 pub fn set_collection_permissions(1058 origin,1059 collection_id: CollectionId,1060 new_permission: CollectionPermissions,1061 ) -> DispatchResult {1062 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1063 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1064 target_collection.check_is_internal()?;1065 target_collection.check_is_owner_or_admin(&sender)?;1066 let old_limit = &target_collection.permissions;10671068 target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_permission)?;10691070 <Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(1071 collection_id1072 ));10731074 target_collection.save()1075 }10761077 /// Re-partition a refungible token, while owning all of its parts/pieces.1078 ///1079 /// # Permissions1080 ///1081 /// * Token owner (must own every part)1082 ///1083 /// # Arguments1084 ///1085 /// * `collection_id`: ID of the collection the RFT belongs to.1086 /// * `token_id`: ID of the RFT.1087 /// * `amount`: New number of parts/pieces into which the token shall be partitioned.1088 #[weight = T::RefungibleExtensionsWeightInfo::repartition()]1089 pub fn repartition(1090 origin,1091 collection_id: CollectionId,1092 token_id: TokenId,1093 amount: u128,1094 ) -> DispatchResultWithPostInfo {1095 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1096 dispatch_tx::<T, _>(collection_id, |d| {1097 if let Some(refungible_extensions) = d.refungible_extensions() {1098 refungible_extensions.repartition(&sender, token_id, amount)1099 } else {1100 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)1101 }1102 })1103 }1104 }1105}tests/src/interfaces/augment-api-events.tsdiffbeforeafterboth--- a/tests/src/interfaces/augment-api-events.ts
+++ b/tests/src/interfaces/augment-api-events.ts
@@ -361,7 +361,7 @@
[key: string]: AugmentedEvent<ApiType>;
};
promotion: {
- StakingRecalculation: AugmentedEvent<ApiType, [u128, u128]>;
+ StakingRecalculation: AugmentedEvent<ApiType, [AccountId32, u128, u128]>;
/**
* Generic event
**/
tests/src/interfaces/augment-api-query.tsdiffbeforeafterboth--- a/tests/src/interfaces/augment-api-query.ts
+++ b/tests/src/interfaces/augment-api-query.ts
@@ -513,6 +513,11 @@
promotion: {
admin: AugmentedQuery<ApiType, () => Observable<Option<AccountId32>>, []> & QueryableStorageEntry<ApiType, []>;
/**
+ * Stores the address of the staker for which the last revenue recalculation was performed.
+ * If `None`, then recalculation has not yet been performed or calculations have been completed for all stakers.
+ **/
+ lastCalcucaltedStaker: AugmentedQuery<ApiType, () => Observable<Option<AccountId32>>, []> & QueryableStorageEntry<ApiType, []>;
+ /**
* Next target block when interest is recalculated
**/
nextInterestBlock: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;
@@ -523,7 +528,7 @@
/**
* Amount of tokens staked by account in the blocknumber.
**/
- staked: AugmentedQuery<ApiType, (arg1: AccountId32 | string | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<u128>, [AccountId32, u32]> & QueryableStorageEntry<ApiType, [AccountId32, u32]>;
+ staked: AugmentedQuery<ApiType, (arg1: AccountId32 | string | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<ITuple<[u128, u32]>>, [AccountId32, u32]> & QueryableStorageEntry<ApiType, [AccountId32, u32]>;
/**
* A block when app-promotion has started .I think this is redundant, because we only need `NextInterestBlock`.
**/
tests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth--- a/tests/src/interfaces/augment-api-tx.ts
+++ b/tests/src/interfaces/augment-api-tx.ts
@@ -363,14 +363,15 @@
[key: string]: SubmittableExtrinsicFunction<ApiType>;
};
promotion: {
+ payoutStakers: AugmentedSubmittable<(stakersNumber: Option<u8> | null | Uint8Array | u8 | AnyNumber) => SubmittableExtrinsic<ApiType>, [Option<u8>]>;
setAdminAddress: AugmentedSubmittable<(admin: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletEvmAccountBasicCrossAccountIdRepr]>;
sponsorCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
sponsorConract: AugmentedSubmittable<(contractId: H160 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [H160]>;
stake: AugmentedSubmittable<(amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u128]>;
startAppPromotion: AugmentedSubmittable<(promotionStartRelayBlock: Option<u32> | null | Uint8Array | u32 | AnyNumber) => SubmittableExtrinsic<ApiType>, [Option<u32>]>;
stopAppPromotion: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
- stopSponsorignCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
- stopSponsorignContract: AugmentedSubmittable<(contractId: H160 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [H160]>;
+ stopSponsoringCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
+ stopSponsoringContract: AugmentedSubmittable<(contractId: H160 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [H160]>;
unstake: AugmentedSubmittable<(amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u128]>;
/**
* Generic tx
tests/src/interfaces/default/types.tsdiffbeforeafterboth--- a/tests/src/interfaces/default/types.ts
+++ b/tests/src/interfaces/default/types.ts
@@ -829,19 +829,23 @@
readonly asSponsorCollection: {
readonly collectionId: u32;
} & Struct;
- readonly isStopSponsorignCollection: boolean;
- readonly asStopSponsorignCollection: {
+ readonly isStopSponsoringCollection: boolean;
+ readonly asStopSponsoringCollection: {
readonly collectionId: u32;
} & Struct;
readonly isSponsorConract: boolean;
readonly asSponsorConract: {
readonly contractId: H160;
} & Struct;
- readonly isStopSponsorignContract: boolean;
- readonly asStopSponsorignContract: {
+ readonly isStopSponsoringContract: boolean;
+ readonly asStopSponsoringContract: {
readonly contractId: H160;
} & Struct;
- readonly type: 'SetAdminAddress' | 'StartAppPromotion' | 'StopAppPromotion' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsorignCollection' | 'SponsorConract' | 'StopSponsorignContract';
+ readonly isPayoutStakers: boolean;
+ readonly asPayoutStakers: {
+ readonly stakersNumber: Option<u8>;
+ } & Struct;
+ readonly type: 'SetAdminAddress' | 'StartAppPromotion' | 'StopAppPromotion' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorConract' | 'StopSponsoringContract' | 'PayoutStakers';
}
/** @name PalletAppPromotionError */
@@ -856,7 +860,7 @@
/** @name PalletAppPromotionEvent */
export interface PalletAppPromotionEvent extends Enum {
readonly isStakingRecalculation: boolean;
- readonly asStakingRecalculation: ITuple<[u128, u128]>;
+ readonly asStakingRecalculation: ITuple<[AccountId32, u128, u128]>;
readonly type: 'StakingRecalculation';
}
tests/src/interfaces/lookup.tsdiffbeforeafterboth--- a/tests/src/interfaces/lookup.ts
+++ b/tests/src/interfaces/lookup.ts
@@ -1061,7 +1061,7 @@
**/
PalletAppPromotionEvent: {
_enum: {
- StakingRecalculation: '(u128,u128)'
+ StakingRecalculation: '(AccountId32,u128,u128)'
}
},
/**
@@ -2473,19 +2473,22 @@
sponsor_collection: {
collectionId: 'u32',
},
- stop_sponsorign_collection: {
+ stop_sponsoring_collection: {
collectionId: 'u32',
},
sponsor_conract: {
contractId: 'H160',
},
- stop_sponsorign_contract: {
- contractId: 'H160'
+ stop_sponsoring_contract: {
+ contractId: 'H160',
+ },
+ payout_stakers: {
+ stakersNumber: 'Option<u8>'
}
}
},
/**
- * Lookup305: pallet_evm::pallet::Call<T>
+ * Lookup306: pallet_evm::pallet::Call<T>
**/
PalletEvmCall: {
_enum: {
@@ -2528,7 +2531,7 @@
}
},
/**
- * Lookup309: pallet_ethereum::pallet::Call<T>
+ * Lookup310: pallet_ethereum::pallet::Call<T>
**/
PalletEthereumCall: {
_enum: {
@@ -2538,7 +2541,7 @@
}
},
/**
- * Lookup310: ethereum::transaction::TransactionV2
+ * Lookup311: ethereum::transaction::TransactionV2
**/
EthereumTransactionTransactionV2: {
_enum: {
@@ -2548,7 +2551,7 @@
}
},
/**
- * Lookup311: ethereum::transaction::LegacyTransaction
+ * Lookup312: ethereum::transaction::LegacyTransaction
**/
EthereumTransactionLegacyTransaction: {
nonce: 'U256',
@@ -2560,7 +2563,7 @@
signature: 'EthereumTransactionTransactionSignature'
},
/**
- * Lookup312: ethereum::transaction::TransactionAction
+ * Lookup313: ethereum::transaction::TransactionAction
**/
EthereumTransactionTransactionAction: {
_enum: {
@@ -2569,7 +2572,7 @@
}
},
/**
- * Lookup313: ethereum::transaction::TransactionSignature
+ * Lookup314: ethereum::transaction::TransactionSignature
**/
EthereumTransactionTransactionSignature: {
v: 'u64',
@@ -2577,7 +2580,7 @@
s: 'H256'
},
/**
- * Lookup315: ethereum::transaction::EIP2930Transaction
+ * Lookup316: ethereum::transaction::EIP2930Transaction
**/
EthereumTransactionEip2930Transaction: {
chainId: 'u64',
@@ -2593,14 +2596,14 @@
s: 'H256'
},
/**
- * Lookup317: ethereum::transaction::AccessListItem
+ * Lookup318: ethereum::transaction::AccessListItem
**/
EthereumTransactionAccessListItem: {
address: 'H160',
storageKeys: 'Vec<H256>'
},
/**
- * Lookup318: ethereum::transaction::EIP1559Transaction
+ * Lookup319: ethereum::transaction::EIP1559Transaction
**/
EthereumTransactionEip1559Transaction: {
chainId: 'u64',
@@ -2617,7 +2620,7 @@
s: 'H256'
},
/**
- * Lookup319: pallet_evm_migration::pallet::Call<T>
+ * Lookup320: pallet_evm_migration::pallet::Call<T>
**/
PalletEvmMigrationCall: {
_enum: {
@@ -2635,19 +2638,19 @@
}
},
/**
- * Lookup322: pallet_sudo::pallet::Error<T>
+ * Lookup323: pallet_sudo::pallet::Error<T>
**/
PalletSudoError: {
_enum: ['RequireSudo']
},
/**
- * Lookup324: orml_vesting::module::Error<T>
+ * Lookup325: orml_vesting::module::Error<T>
**/
OrmlVestingModuleError: {
_enum: ['ZeroVestingPeriod', 'ZeroVestingPeriodCount', 'InsufficientBalanceToLock', 'TooManyVestingSchedules', 'AmountLow', 'MaxVestingSchedulesExceeded']
},
/**
- * Lookup326: cumulus_pallet_xcmp_queue::InboundChannelDetails
+ * Lookup327: cumulus_pallet_xcmp_queue::InboundChannelDetails
**/
CumulusPalletXcmpQueueInboundChannelDetails: {
sender: 'u32',
@@ -2655,19 +2658,19 @@
messageMetadata: 'Vec<(u32,PolkadotParachainPrimitivesXcmpMessageFormat)>'
},
/**
- * Lookup327: cumulus_pallet_xcmp_queue::InboundState
+ * Lookup328: cumulus_pallet_xcmp_queue::InboundState
**/
CumulusPalletXcmpQueueInboundState: {
_enum: ['Ok', 'Suspended']
},
/**
- * Lookup330: polkadot_parachain::primitives::XcmpMessageFormat
+ * Lookup331: polkadot_parachain::primitives::XcmpMessageFormat
**/
PolkadotParachainPrimitivesXcmpMessageFormat: {
_enum: ['ConcatenatedVersionedXcm', 'ConcatenatedEncodedBlob', 'Signals']
},
/**
- * Lookup333: cumulus_pallet_xcmp_queue::OutboundChannelDetails
+ * Lookup334: cumulus_pallet_xcmp_queue::OutboundChannelDetails
**/
CumulusPalletXcmpQueueOutboundChannelDetails: {
recipient: 'u32',
@@ -2677,13 +2680,13 @@
lastIndex: 'u16'
},
/**
- * Lookup334: cumulus_pallet_xcmp_queue::OutboundState
+ * Lookup335: cumulus_pallet_xcmp_queue::OutboundState
**/
CumulusPalletXcmpQueueOutboundState: {
_enum: ['Ok', 'Suspended']
},
/**
- * Lookup336: cumulus_pallet_xcmp_queue::QueueConfigData
+ * Lookup337: cumulus_pallet_xcmp_queue::QueueConfigData
**/
CumulusPalletXcmpQueueQueueConfigData: {
suspendThreshold: 'u32',
@@ -2694,29 +2697,29 @@
xcmpMaxIndividualWeight: 'u64'
},
/**
- * Lookup338: cumulus_pallet_xcmp_queue::pallet::Error<T>
+ * Lookup339: cumulus_pallet_xcmp_queue::pallet::Error<T>
**/
CumulusPalletXcmpQueueError: {
_enum: ['FailedToSend', 'BadXcmOrigin', 'BadXcm', 'BadOverweightIndex', 'WeightOverLimit']
},
/**
- * Lookup339: pallet_xcm::pallet::Error<T>
+ * Lookup340: pallet_xcm::pallet::Error<T>
**/
PalletXcmError: {
_enum: ['Unreachable', 'SendFailure', 'Filtered', 'UnweighableMessage', 'DestinationNotInvertible', 'Empty', 'CannotReanchor', 'TooManyAssets', 'InvalidOrigin', 'BadVersion', 'BadLocation', 'NoSubscription', 'AlreadySubscribed']
},
/**
- * Lookup340: cumulus_pallet_xcm::pallet::Error<T>
+ * Lookup341: cumulus_pallet_xcm::pallet::Error<T>
**/
CumulusPalletXcmError: 'Null',
/**
- * Lookup341: cumulus_pallet_dmp_queue::ConfigData
+ * Lookup342: cumulus_pallet_dmp_queue::ConfigData
**/
CumulusPalletDmpQueueConfigData: {
maxIndividual: 'u64'
},
/**
- * Lookup342: cumulus_pallet_dmp_queue::PageIndexData
+ * Lookup343: cumulus_pallet_dmp_queue::PageIndexData
**/
CumulusPalletDmpQueuePageIndexData: {
beginUsed: 'u32',
@@ -2724,19 +2727,19 @@
overweightCount: 'u64'
},
/**
- * Lookup345: cumulus_pallet_dmp_queue::pallet::Error<T>
+ * Lookup346: cumulus_pallet_dmp_queue::pallet::Error<T>
**/
CumulusPalletDmpQueueError: {
_enum: ['Unknown', 'OverLimit']
},
/**
- * Lookup349: pallet_unique::Error<T>
+ * Lookup350: pallet_unique::Error<T>
**/
PalletUniqueError: {
_enum: ['CollectionDecimalPointLimitExceeded', 'ConfirmUnsetSponsorFail', 'EmptyArgument', 'RepartitionCalledOnNonRefungibleCollection']
},
/**
- * Lookup352: pallet_unique_scheduler::ScheduledV3<frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32>
+ * Lookup353: pallet_unique_scheduler::ScheduledV3<frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32>
**/
PalletUniqueSchedulerScheduledV3: {
maybeId: 'Option<[u8;16]>',
@@ -2746,7 +2749,7 @@
origin: 'OpalRuntimeOriginCaller'
},
/**
- * Lookup353: opal_runtime::OriginCaller
+ * Lookup354: opal_runtime::OriginCaller
**/
OpalRuntimeOriginCaller: {
_enum: {
@@ -2855,7 +2858,7 @@
}
},
/**
- * Lookup354: frame_support::dispatch::RawOrigin<sp_core::crypto::AccountId32>
+ * Lookup355: frame_support::dispatch::RawOrigin<sp_core::crypto::AccountId32>
**/
FrameSupportDispatchRawOrigin: {
_enum: {
@@ -2865,7 +2868,7 @@
}
},
/**
- * Lookup355: pallet_xcm::pallet::Origin
+ * Lookup356: pallet_xcm::pallet::Origin
**/
PalletXcmOrigin: {
_enum: {
@@ -2874,7 +2877,7 @@
}
},
/**
- * Lookup356: cumulus_pallet_xcm::pallet::Origin
+ * Lookup357: cumulus_pallet_xcm::pallet::Origin
**/
CumulusPalletXcmOrigin: {
_enum: {
@@ -2883,7 +2886,7 @@
}
},
/**
- * Lookup357: pallet_ethereum::RawOrigin
+ * Lookup358: pallet_ethereum::RawOrigin
**/
PalletEthereumRawOrigin: {
_enum: {
@@ -2891,17 +2894,17 @@
}
},
/**
- * Lookup358: sp_core::Void
+ * Lookup359: sp_core::Void
**/
SpCoreVoid: 'Null',
/**
- * Lookup359: pallet_unique_scheduler::pallet::Error<T>
+ * Lookup360: pallet_unique_scheduler::pallet::Error<T>
**/
PalletUniqueSchedulerError: {
_enum: ['FailedToSchedule', 'NotFound', 'TargetBlockNumberInPast', 'RescheduleNoChange']
},
/**
- * Lookup360: up_data_structs::Collection<sp_core::crypto::AccountId32>
+ * Lookup361: up_data_structs::Collection<sp_core::crypto::AccountId32>
**/
UpDataStructsCollection: {
owner: 'AccountId32',
@@ -2915,7 +2918,7 @@
externalCollection: 'bool'
},
/**
- * Lookup361: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>
+ * Lookup362: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>
**/
UpDataStructsSponsorshipStateAccountId32: {
_enum: {
@@ -2925,7 +2928,7 @@
}
},
/**
- * Lookup362: up_data_structs::Properties
+ * Lookup363: up_data_structs::Properties
**/
UpDataStructsProperties: {
map: 'UpDataStructsPropertiesMapBoundedVec',
@@ -2933,15 +2936,15 @@
spaceLimit: 'u32'
},
/**
- * Lookup363: up_data_structs::PropertiesMap<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>
+ * Lookup364: up_data_structs::PropertiesMap<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>
**/
UpDataStructsPropertiesMapBoundedVec: 'BTreeMap<Bytes, Bytes>',
/**
- * Lookup368: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>
+ * Lookup369: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>
**/
UpDataStructsPropertiesMapPropertyPermission: 'BTreeMap<Bytes, UpDataStructsPropertyPermission>',
/**
- * Lookup375: up_data_structs::CollectionStats
+ * Lookup376: up_data_structs::CollectionStats
**/
UpDataStructsCollectionStats: {
created: 'u32',
@@ -2949,18 +2952,18 @@
alive: 'u32'
},
/**
- * Lookup376: up_data_structs::TokenChild
+ * Lookup377: up_data_structs::TokenChild
**/
UpDataStructsTokenChild: {
token: 'u32',
collection: 'u32'
},
/**
- * Lookup377: PhantomType::up_data_structs<T>
+ * Lookup378: PhantomType::up_data_structs<T>
**/
PhantomTypeUpDataStructs: '[(UpDataStructsTokenData,UpDataStructsRpcCollection,RmrkTraitsCollectionCollectionInfo,RmrkTraitsNftNftInfo,RmrkTraitsResourceResourceInfo,RmrkTraitsPropertyPropertyInfo,RmrkTraitsBaseBaseInfo,RmrkTraitsPartPartType,RmrkTraitsTheme,RmrkTraitsNftNftChild);0]',
/**
- * Lookup379: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+ * Lookup380: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
**/
UpDataStructsTokenData: {
properties: 'Vec<UpDataStructsProperty>',
@@ -2968,7 +2971,7 @@
pieces: 'u128'
},
/**
- * Lookup381: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>
+ * Lookup382: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>
**/
UpDataStructsRpcCollection: {
owner: 'AccountId32',
@@ -2984,7 +2987,7 @@
readOnly: 'bool'
},
/**
- * Lookup382: rmrk_traits::collection::CollectionInfo<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>
+ * Lookup383: rmrk_traits::collection::CollectionInfo<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>
**/
RmrkTraitsCollectionCollectionInfo: {
issuer: 'AccountId32',
@@ -2994,7 +2997,7 @@
nftsCount: 'u32'
},
/**
- * Lookup383: rmrk_traits::nft::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>
+ * Lookup384: rmrk_traits::nft::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>
**/
RmrkTraitsNftNftInfo: {
owner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',
@@ -3004,14 +3007,14 @@
pending: 'bool'
},
/**
- * Lookup385: rmrk_traits::nft::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>
+ * Lookup386: rmrk_traits::nft::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>
**/
RmrkTraitsNftRoyaltyInfo: {
recipient: 'AccountId32',
amount: 'Permill'
},
/**
- * Lookup386: rmrk_traits::resource::ResourceInfo<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>
+ * Lookup387: rmrk_traits::resource::ResourceInfo<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>
**/
RmrkTraitsResourceResourceInfo: {
id: 'u32',
@@ -3020,14 +3023,14 @@
pendingRemoval: 'bool'
},
/**
- * Lookup387: rmrk_traits::property::PropertyInfo<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>
+ * Lookup388: rmrk_traits::property::PropertyInfo<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>
**/
RmrkTraitsPropertyPropertyInfo: {
key: 'Bytes',
value: 'Bytes'
},
/**
- * Lookup388: rmrk_traits::base::BaseInfo<sp_core::crypto::AccountId32, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>
+ * Lookup389: rmrk_traits::base::BaseInfo<sp_core::crypto::AccountId32, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>
**/
RmrkTraitsBaseBaseInfo: {
issuer: 'AccountId32',
@@ -3035,86 +3038,86 @@
symbol: 'Bytes'
},
/**
- * Lookup389: rmrk_traits::nft::NftChild
+ * Lookup390: rmrk_traits::nft::NftChild
**/
RmrkTraitsNftNftChild: {
collectionId: 'u32',
nftId: 'u32'
},
/**
- * Lookup391: pallet_common::pallet::Error<T>
+ * Lookup392: pallet_common::pallet::Error<T>
**/
PalletCommonError: {
_enum: ['CollectionNotFound', 'MustBeTokenOwner', 'NoPermission', 'CantDestroyNotEmptyCollection', 'PublicMintingNotAllowed', 'AddressNotInAllowlist', 'CollectionNameLimitExceeded', 'CollectionDescriptionLimitExceeded', 'CollectionTokenPrefixLimitExceeded', 'TotalCollectionsLimitExceeded', 'CollectionAdminCountExceeded', 'CollectionLimitBoundsExceeded', 'OwnerPermissionsCantBeReverted', 'TransferNotAllowed', 'AccountTokenLimitExceeded', 'CollectionTokenLimitExceeded', 'MetadataFlagFrozen', 'TokenNotFound', 'TokenValueTooLow', 'ApprovedValueTooLow', 'CantApproveMoreThanOwned', 'AddressIsZero', 'UnsupportedOperation', 'NotSufficientFounds', 'UserIsNotAllowedToNest', 'SourceCollectionIsNotAllowedToNest', 'CollectionFieldSizeExceeded', 'NoSpaceForProperty', 'PropertyLimitReached', 'PropertyKeyIsTooLong', 'InvalidCharacterInPropertyKey', 'EmptyPropertyKey', 'CollectionIsExternal', 'CollectionIsInternal']
},
/**
- * Lookup393: pallet_fungible::pallet::Error<T>
+ * Lookup394: pallet_fungible::pallet::Error<T>
**/
PalletFungibleError: {
_enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed']
},
/**
- * Lookup394: pallet_refungible::ItemData
+ * Lookup395: pallet_refungible::ItemData
**/
PalletRefungibleItemData: {
constData: 'Bytes'
},
/**
- * Lookup399: pallet_refungible::pallet::Error<T>
+ * Lookup400: pallet_refungible::pallet::Error<T>
**/
PalletRefungibleError: {
_enum: ['NotRefungibleDataUsedToMintFungibleCollectionToken', 'WrongRefungiblePieces', 'RepartitionWhileNotOwningAllPieces', 'RefungibleDisallowsNesting', 'SettingPropertiesNotAllowed']
},
/**
- * Lookup400: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+ * Lookup401: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
**/
PalletNonfungibleItemData: {
owner: 'PalletEvmAccountBasicCrossAccountIdRepr'
},
/**
- * Lookup402: up_data_structs::PropertyScope
+ * Lookup403: up_data_structs::PropertyScope
**/
UpDataStructsPropertyScope: {
_enum: ['None', 'Rmrk', 'Eth']
},
/**
- * Lookup404: pallet_nonfungible::pallet::Error<T>
+ * Lookup405: pallet_nonfungible::pallet::Error<T>
**/
PalletNonfungibleError: {
_enum: ['NotNonfungibleDataUsedToMintFungibleCollectionToken', 'NonfungibleItemsHaveNoAmount', 'CantBurnNftWithChildren']
},
/**
- * Lookup405: pallet_structure::pallet::Error<T>
+ * Lookup406: pallet_structure::pallet::Error<T>
**/
PalletStructureError: {
_enum: ['OuroborosDetected', 'DepthLimit', 'BreadthLimit', 'TokenNotFound']
},
/**
- * Lookup406: pallet_rmrk_core::pallet::Error<T>
+ * Lookup407: pallet_rmrk_core::pallet::Error<T>
**/
PalletRmrkCoreError: {
_enum: ['CorruptedCollectionType', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'RmrkPropertyIsNotFound', 'UnableToDecodeRmrkData', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'CannotRejectNonPendingNft', 'ResourceNotPending', 'NoAvailableResourceId']
},
/**
- * Lookup408: pallet_rmrk_equip::pallet::Error<T>
+ * Lookup409: pallet_rmrk_equip::pallet::Error<T>
**/
PalletRmrkEquipError: {
_enum: ['PermissionError', 'NoAvailableBaseId', 'NoAvailablePartId', 'BaseDoesntExist', 'NeedsDefaultThemeFirst', 'PartDoesntExist', 'NoEquippableOnFixedPart']
},
/**
- * Lookup410: pallet_app_promotion::pallet::Error<T>
+ * Lookup412: pallet_app_promotion::pallet::Error<T>
**/
PalletAppPromotionError: {
_enum: ['AdminNotSet', 'NoPermission', 'NotSufficientFounds', 'InvalidArgument']
},
/**
- * Lookup413: pallet_evm::pallet::Error<T>
+ * Lookup415: pallet_evm::pallet::Error<T>
**/
PalletEvmError: {
_enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce']
},
/**
- * Lookup416: fp_rpc::TransactionStatus
+ * Lookup418: fp_rpc::TransactionStatus
**/
FpRpcTransactionStatus: {
transactionHash: 'H256',
@@ -3126,11 +3129,11 @@
logsBloom: 'EthbloomBloom'
},
/**
- * Lookup418: ethbloom::Bloom
+ * Lookup420: ethbloom::Bloom
**/
EthbloomBloom: '[u8;256]',
/**
- * Lookup420: ethereum::receipt::ReceiptV3
+ * Lookup422: ethereum::receipt::ReceiptV3
**/
EthereumReceiptReceiptV3: {
_enum: {
@@ -3140,7 +3143,7 @@
}
},
/**
- * Lookup421: ethereum::receipt::EIP658ReceiptData
+ * Lookup423: ethereum::receipt::EIP658ReceiptData
**/
EthereumReceiptEip658ReceiptData: {
statusCode: 'u8',
@@ -3149,7 +3152,7 @@
logs: 'Vec<EthereumLog>'
},
/**
- * Lookup422: ethereum::block::Block<ethereum::transaction::TransactionV2>
+ * Lookup424: ethereum::block::Block<ethereum::transaction::TransactionV2>
**/
EthereumBlock: {
header: 'EthereumHeader',
@@ -3157,7 +3160,7 @@
ommers: 'Vec<EthereumHeader>'
},
/**
- * Lookup423: ethereum::header::Header
+ * Lookup425: ethereum::header::Header
**/
EthereumHeader: {
parentHash: 'H256',
@@ -3177,23 +3180,23 @@
nonce: 'EthereumTypesHashH64'
},
/**
- * Lookup424: ethereum_types::hash::H64
+ * Lookup426: ethereum_types::hash::H64
**/
EthereumTypesHashH64: '[u8;8]',
/**
- * Lookup429: pallet_ethereum::pallet::Error<T>
+ * Lookup431: pallet_ethereum::pallet::Error<T>
**/
PalletEthereumError: {
_enum: ['InvalidSignature', 'PreLogExists']
},
/**
- * Lookup430: pallet_evm_coder_substrate::pallet::Error<T>
+ * Lookup432: pallet_evm_coder_substrate::pallet::Error<T>
**/
PalletEvmCoderSubstrateError: {
_enum: ['OutOfGas', 'OutOfFund']
},
/**
- * Lookup431: up_data_structs::SponsorshipState<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+ * Lookup433: up_data_structs::SponsorshipState<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
**/
UpDataStructsSponsorshipStateBasicCrossAccountIdRepr: {
_enum: {
@@ -3203,25 +3206,25 @@
}
},
/**
- * Lookup432: pallet_evm_contract_helpers::SponsoringModeT
+ * Lookup434: pallet_evm_contract_helpers::SponsoringModeT
**/
PalletEvmContractHelpersSponsoringModeT: {
_enum: ['Disabled', 'Allowlisted', 'Generous']
},
/**
- * Lookup434: pallet_evm_contract_helpers::pallet::Error<T>
+ * Lookup436: pallet_evm_contract_helpers::pallet::Error<T>
**/
PalletEvmContractHelpersError: {
_enum: ['NoPermission', 'NoPendingSponsor']
},
/**
- * Lookup435: pallet_evm_migration::pallet::Error<T>
+ * Lookup437: pallet_evm_migration::pallet::Error<T>
**/
PalletEvmMigrationError: {
_enum: ['AccountNotEmpty', 'AccountIsNotMigrating']
},
/**
- * Lookup437: sp_runtime::MultiSignature
+ * Lookup439: sp_runtime::MultiSignature
**/
SpRuntimeMultiSignature: {
_enum: {
@@ -3231,43 +3234,43 @@
}
},
/**
- * Lookup438: sp_core::ed25519::Signature
+ * Lookup440: sp_core::ed25519::Signature
**/
SpCoreEd25519Signature: '[u8;64]',
/**
- * Lookup440: sp_core::sr25519::Signature
+ * Lookup442: sp_core::sr25519::Signature
**/
SpCoreSr25519Signature: '[u8;64]',
/**
- * Lookup441: sp_core::ecdsa::Signature
+ * Lookup443: sp_core::ecdsa::Signature
**/
SpCoreEcdsaSignature: '[u8;65]',
/**
- * Lookup444: frame_system::extensions::check_spec_version::CheckSpecVersion<T>
+ * Lookup446: frame_system::extensions::check_spec_version::CheckSpecVersion<T>
**/
FrameSystemExtensionsCheckSpecVersion: 'Null',
/**
- * Lookup445: frame_system::extensions::check_genesis::CheckGenesis<T>
+ * Lookup447: frame_system::extensions::check_genesis::CheckGenesis<T>
**/
FrameSystemExtensionsCheckGenesis: 'Null',
/**
- * Lookup448: frame_system::extensions::check_nonce::CheckNonce<T>
+ * Lookup450: frame_system::extensions::check_nonce::CheckNonce<T>
**/
FrameSystemExtensionsCheckNonce: 'Compact<u32>',
/**
- * Lookup449: frame_system::extensions::check_weight::CheckWeight<T>
+ * Lookup451: frame_system::extensions::check_weight::CheckWeight<T>
**/
FrameSystemExtensionsCheckWeight: 'Null',
/**
- * Lookup450: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>
+ * Lookup452: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>
**/
PalletTemplateTransactionPaymentChargeTransactionPayment: 'Compact<u128>',
/**
- * Lookup451: opal_runtime::Runtime
+ * Lookup453: opal_runtime::Runtime
**/
OpalRuntimeRuntime: 'Null',
/**
- * Lookup452: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>
+ * Lookup454: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>
**/
PalletEthereumFakeTransactionFinalizer: 'Null'
};
tests/src/interfaces/types-lookup.tsdiffbeforeafterboth--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -1201,7 +1201,7 @@
/** @name PalletAppPromotionEvent (103) */
interface PalletAppPromotionEvent extends Enum {
readonly isStakingRecalculation: boolean;
- readonly asStakingRecalculation: ITuple<[u128, u128]>;
+ readonly asStakingRecalculation: ITuple<[AccountId32, u128, u128]>;
readonly type: 'StakingRecalculation';
}
@@ -2682,22 +2682,26 @@
readonly asSponsorCollection: {
readonly collectionId: u32;
} & Struct;
- readonly isStopSponsorignCollection: boolean;
- readonly asStopSponsorignCollection: {
+ readonly isStopSponsoringCollection: boolean;
+ readonly asStopSponsoringCollection: {
readonly collectionId: u32;
} & Struct;
readonly isSponsorConract: boolean;
readonly asSponsorConract: {
readonly contractId: H160;
} & Struct;
- readonly isStopSponsorignContract: boolean;
- readonly asStopSponsorignContract: {
+ readonly isStopSponsoringContract: boolean;
+ readonly asStopSponsoringContract: {
readonly contractId: H160;
} & Struct;
- readonly type: 'SetAdminAddress' | 'StartAppPromotion' | 'StopAppPromotion' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsorignCollection' | 'SponsorConract' | 'StopSponsorignContract';
+ readonly isPayoutStakers: boolean;
+ readonly asPayoutStakers: {
+ readonly stakersNumber: Option<u8>;
+ } & Struct;
+ readonly type: 'SetAdminAddress' | 'StartAppPromotion' | 'StopAppPromotion' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorConract' | 'StopSponsoringContract' | 'PayoutStakers';
}
- /** @name PalletEvmCall (305) */
+ /** @name PalletEvmCall (306) */
interface PalletEvmCall extends Enum {
readonly isWithdraw: boolean;
readonly asWithdraw: {
@@ -2742,7 +2746,7 @@
readonly type: 'Withdraw' | 'Call' | 'Create' | 'Create2';
}
- /** @name PalletEthereumCall (309) */
+ /** @name PalletEthereumCall (310) */
interface PalletEthereumCall extends Enum {
readonly isTransact: boolean;
readonly asTransact: {
@@ -2751,7 +2755,7 @@
readonly type: 'Transact';
}
- /** @name EthereumTransactionTransactionV2 (310) */
+ /** @name EthereumTransactionTransactionV2 (311) */
interface EthereumTransactionTransactionV2 extends Enum {
readonly isLegacy: boolean;
readonly asLegacy: EthereumTransactionLegacyTransaction;
@@ -2762,7 +2766,7 @@
readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
}
- /** @name EthereumTransactionLegacyTransaction (311) */
+ /** @name EthereumTransactionLegacyTransaction (312) */
interface EthereumTransactionLegacyTransaction extends Struct {
readonly nonce: U256;
readonly gasPrice: U256;
@@ -2773,7 +2777,7 @@
readonly signature: EthereumTransactionTransactionSignature;
}
- /** @name EthereumTransactionTransactionAction (312) */
+ /** @name EthereumTransactionTransactionAction (313) */
interface EthereumTransactionTransactionAction extends Enum {
readonly isCall: boolean;
readonly asCall: H160;
@@ -2781,14 +2785,14 @@
readonly type: 'Call' | 'Create';
}
- /** @name EthereumTransactionTransactionSignature (313) */
+ /** @name EthereumTransactionTransactionSignature (314) */
interface EthereumTransactionTransactionSignature extends Struct {
readonly v: u64;
readonly r: H256;
readonly s: H256;
}
- /** @name EthereumTransactionEip2930Transaction (315) */
+ /** @name EthereumTransactionEip2930Transaction (316) */
interface EthereumTransactionEip2930Transaction extends Struct {
readonly chainId: u64;
readonly nonce: U256;
@@ -2803,13 +2807,13 @@
readonly s: H256;
}
- /** @name EthereumTransactionAccessListItem (317) */
+ /** @name EthereumTransactionAccessListItem (318) */
interface EthereumTransactionAccessListItem extends Struct {
readonly address: H160;
readonly storageKeys: Vec<H256>;
}
- /** @name EthereumTransactionEip1559Transaction (318) */
+ /** @name EthereumTransactionEip1559Transaction (319) */
interface EthereumTransactionEip1559Transaction extends Struct {
readonly chainId: u64;
readonly nonce: U256;
@@ -2825,7 +2829,7 @@
readonly s: H256;
}
- /** @name PalletEvmMigrationCall (319) */
+ /** @name PalletEvmMigrationCall (320) */
interface PalletEvmMigrationCall extends Enum {
readonly isBegin: boolean;
readonly asBegin: {
@@ -2844,13 +2848,13 @@
readonly type: 'Begin' | 'SetData' | 'Finish';
}
- /** @name PalletSudoError (322) */
+ /** @name PalletSudoError (323) */
interface PalletSudoError extends Enum {
readonly isRequireSudo: boolean;
readonly type: 'RequireSudo';
}
- /** @name OrmlVestingModuleError (324) */
+ /** @name OrmlVestingModuleError (325) */
interface OrmlVestingModuleError extends Enum {
readonly isZeroVestingPeriod: boolean;
readonly isZeroVestingPeriodCount: boolean;
@@ -2861,21 +2865,21 @@
readonly type: 'ZeroVestingPeriod' | 'ZeroVestingPeriodCount' | 'InsufficientBalanceToLock' | 'TooManyVestingSchedules' | 'AmountLow' | 'MaxVestingSchedulesExceeded';
}
- /** @name CumulusPalletXcmpQueueInboundChannelDetails (326) */
+ /** @name CumulusPalletXcmpQueueInboundChannelDetails (327) */
interface CumulusPalletXcmpQueueInboundChannelDetails extends Struct {
readonly sender: u32;
readonly state: CumulusPalletXcmpQueueInboundState;
readonly messageMetadata: Vec<ITuple<[u32, PolkadotParachainPrimitivesXcmpMessageFormat]>>;
}
- /** @name CumulusPalletXcmpQueueInboundState (327) */
+ /** @name CumulusPalletXcmpQueueInboundState (328) */
interface CumulusPalletXcmpQueueInboundState extends Enum {
readonly isOk: boolean;
readonly isSuspended: boolean;
readonly type: 'Ok' | 'Suspended';
}
- /** @name PolkadotParachainPrimitivesXcmpMessageFormat (330) */
+ /** @name PolkadotParachainPrimitivesXcmpMessageFormat (331) */
interface PolkadotParachainPrimitivesXcmpMessageFormat extends Enum {
readonly isConcatenatedVersionedXcm: boolean;
readonly isConcatenatedEncodedBlob: boolean;
@@ -2883,7 +2887,7 @@
readonly type: 'ConcatenatedVersionedXcm' | 'ConcatenatedEncodedBlob' | 'Signals';
}
- /** @name CumulusPalletXcmpQueueOutboundChannelDetails (333) */
+ /** @name CumulusPalletXcmpQueueOutboundChannelDetails (334) */
interface CumulusPalletXcmpQueueOutboundChannelDetails extends Struct {
readonly recipient: u32;
readonly state: CumulusPalletXcmpQueueOutboundState;
@@ -2892,14 +2896,14 @@
readonly lastIndex: u16;
}
- /** @name CumulusPalletXcmpQueueOutboundState (334) */
+ /** @name CumulusPalletXcmpQueueOutboundState (335) */
interface CumulusPalletXcmpQueueOutboundState extends Enum {
readonly isOk: boolean;
readonly isSuspended: boolean;
readonly type: 'Ok' | 'Suspended';
}
- /** @name CumulusPalletXcmpQueueQueueConfigData (336) */
+ /** @name CumulusPalletXcmpQueueQueueConfigData (337) */
interface CumulusPalletXcmpQueueQueueConfigData extends Struct {
readonly suspendThreshold: u32;
readonly dropThreshold: u32;
@@ -2909,7 +2913,7 @@
readonly xcmpMaxIndividualWeight: u64;
}
- /** @name CumulusPalletXcmpQueueError (338) */
+ /** @name CumulusPalletXcmpQueueError (339) */
interface CumulusPalletXcmpQueueError extends Enum {
readonly isFailedToSend: boolean;
readonly isBadXcmOrigin: boolean;
@@ -2919,7 +2923,7 @@
readonly type: 'FailedToSend' | 'BadXcmOrigin' | 'BadXcm' | 'BadOverweightIndex' | 'WeightOverLimit';
}
- /** @name PalletXcmError (339) */
+ /** @name PalletXcmError (340) */
interface PalletXcmError extends Enum {
readonly isUnreachable: boolean;
readonly isSendFailure: boolean;
@@ -2937,29 +2941,29 @@
readonly type: 'Unreachable' | 'SendFailure' | 'Filtered' | 'UnweighableMessage' | 'DestinationNotInvertible' | 'Empty' | 'CannotReanchor' | 'TooManyAssets' | 'InvalidOrigin' | 'BadVersion' | 'BadLocation' | 'NoSubscription' | 'AlreadySubscribed';
}
- /** @name CumulusPalletXcmError (340) */
+ /** @name CumulusPalletXcmError (341) */
type CumulusPalletXcmError = Null;
- /** @name CumulusPalletDmpQueueConfigData (341) */
+ /** @name CumulusPalletDmpQueueConfigData (342) */
interface CumulusPalletDmpQueueConfigData extends Struct {
readonly maxIndividual: u64;
}
- /** @name CumulusPalletDmpQueuePageIndexData (342) */
+ /** @name CumulusPalletDmpQueuePageIndexData (343) */
interface CumulusPalletDmpQueuePageIndexData extends Struct {
readonly beginUsed: u32;
readonly endUsed: u32;
readonly overweightCount: u64;
}
- /** @name CumulusPalletDmpQueueError (345) */
+ /** @name CumulusPalletDmpQueueError (346) */
interface CumulusPalletDmpQueueError extends Enum {
readonly isUnknown: boolean;
readonly isOverLimit: boolean;
readonly type: 'Unknown' | 'OverLimit';
}
- /** @name PalletUniqueError (349) */
+ /** @name PalletUniqueError (350) */
interface PalletUniqueError extends Enum {
readonly isCollectionDecimalPointLimitExceeded: boolean;
readonly isConfirmUnsetSponsorFail: boolean;
@@ -2968,7 +2972,7 @@
readonly type: 'CollectionDecimalPointLimitExceeded' | 'ConfirmUnsetSponsorFail' | 'EmptyArgument' | 'RepartitionCalledOnNonRefungibleCollection';
}
- /** @name PalletUniqueSchedulerScheduledV3 (352) */
+ /** @name PalletUniqueSchedulerScheduledV3 (353) */
interface PalletUniqueSchedulerScheduledV3 extends Struct {
readonly maybeId: Option<U8aFixed>;
readonly priority: u8;
@@ -2977,7 +2981,7 @@
readonly origin: OpalRuntimeOriginCaller;
}
- /** @name OpalRuntimeOriginCaller (353) */
+ /** @name OpalRuntimeOriginCaller (354) */
interface OpalRuntimeOriginCaller extends Enum {
readonly isSystem: boolean;
readonly asSystem: FrameSupportDispatchRawOrigin;
@@ -2991,7 +2995,7 @@
readonly type: 'System' | 'Void' | 'PolkadotXcm' | 'CumulusXcm' | 'Ethereum';
}
- /** @name FrameSupportDispatchRawOrigin (354) */
+ /** @name FrameSupportDispatchRawOrigin (355) */
interface FrameSupportDispatchRawOrigin extends Enum {
readonly isRoot: boolean;
readonly isSigned: boolean;
@@ -3000,7 +3004,7 @@
readonly type: 'Root' | 'Signed' | 'None';
}
- /** @name PalletXcmOrigin (355) */
+ /** @name PalletXcmOrigin (356) */
interface PalletXcmOrigin extends Enum {
readonly isXcm: boolean;
readonly asXcm: XcmV1MultiLocation;
@@ -3009,7 +3013,7 @@
readonly type: 'Xcm' | 'Response';
}
- /** @name CumulusPalletXcmOrigin (356) */
+ /** @name CumulusPalletXcmOrigin (357) */
interface CumulusPalletXcmOrigin extends Enum {
readonly isRelay: boolean;
readonly isSiblingParachain: boolean;
@@ -3017,17 +3021,17 @@
readonly type: 'Relay' | 'SiblingParachain';
}
- /** @name PalletEthereumRawOrigin (357) */
+ /** @name PalletEthereumRawOrigin (358) */
interface PalletEthereumRawOrigin extends Enum {
readonly isEthereumTransaction: boolean;
readonly asEthereumTransaction: H160;
readonly type: 'EthereumTransaction';
}
- /** @name SpCoreVoid (358) */
+ /** @name SpCoreVoid (359) */
type SpCoreVoid = Null;
- /** @name PalletUniqueSchedulerError (359) */
+ /** @name PalletUniqueSchedulerError (360) */
interface PalletUniqueSchedulerError extends Enum {
readonly isFailedToSchedule: boolean;
readonly isNotFound: boolean;
@@ -3036,7 +3040,7 @@
readonly type: 'FailedToSchedule' | 'NotFound' | 'TargetBlockNumberInPast' | 'RescheduleNoChange';
}
- /** @name UpDataStructsCollection (360) */
+ /** @name UpDataStructsCollection (361) */
interface UpDataStructsCollection extends Struct {
readonly owner: AccountId32;
readonly mode: UpDataStructsCollectionMode;
@@ -3049,7 +3053,7 @@
readonly externalCollection: bool;
}
- /** @name UpDataStructsSponsorshipStateAccountId32 (361) */
+ /** @name UpDataStructsSponsorshipStateAccountId32 (362) */
interface UpDataStructsSponsorshipStateAccountId32 extends Enum {
readonly isDisabled: boolean;
readonly isUnconfirmed: boolean;
@@ -3059,43 +3063,43 @@
readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed';
}
- /** @name UpDataStructsProperties (362) */
+ /** @name UpDataStructsProperties (363) */
interface UpDataStructsProperties extends Struct {
readonly map: UpDataStructsPropertiesMapBoundedVec;
readonly consumedSpace: u32;
readonly spaceLimit: u32;
}
- /** @name UpDataStructsPropertiesMapBoundedVec (363) */
+ /** @name UpDataStructsPropertiesMapBoundedVec (364) */
interface UpDataStructsPropertiesMapBoundedVec extends BTreeMap<Bytes, Bytes> {}
- /** @name UpDataStructsPropertiesMapPropertyPermission (368) */
+ /** @name UpDataStructsPropertiesMapPropertyPermission (369) */
interface UpDataStructsPropertiesMapPropertyPermission extends BTreeMap<Bytes, UpDataStructsPropertyPermission> {}
- /** @name UpDataStructsCollectionStats (375) */
+ /** @name UpDataStructsCollectionStats (376) */
interface UpDataStructsCollectionStats extends Struct {
readonly created: u32;
readonly destroyed: u32;
readonly alive: u32;
}
- /** @name UpDataStructsTokenChild (376) */
+ /** @name UpDataStructsTokenChild (377) */
interface UpDataStructsTokenChild extends Struct {
readonly token: u32;
readonly collection: u32;
}
- /** @name PhantomTypeUpDataStructs (377) */
+ /** @name PhantomTypeUpDataStructs (378) */
interface PhantomTypeUpDataStructs extends Vec<ITuple<[UpDataStructsTokenData, UpDataStructsRpcCollection, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftNftInfo, RmrkTraitsResourceResourceInfo, RmrkTraitsPropertyPropertyInfo, RmrkTraitsBaseBaseInfo, RmrkTraitsPartPartType, RmrkTraitsTheme, RmrkTraitsNftNftChild]>> {}
- /** @name UpDataStructsTokenData (379) */
+ /** @name UpDataStructsTokenData (380) */
interface UpDataStructsTokenData extends Struct {
readonly properties: Vec<UpDataStructsProperty>;
readonly owner: Option<PalletEvmAccountBasicCrossAccountIdRepr>;
readonly pieces: u128;
}
- /** @name UpDataStructsRpcCollection (381) */
+ /** @name UpDataStructsRpcCollection (382) */
interface UpDataStructsRpcCollection extends Struct {
readonly owner: AccountId32;
readonly mode: UpDataStructsCollectionMode;
@@ -3110,7 +3114,7 @@
readonly readOnly: bool;
}
- /** @name RmrkTraitsCollectionCollectionInfo (382) */
+ /** @name RmrkTraitsCollectionCollectionInfo (383) */
interface RmrkTraitsCollectionCollectionInfo extends Struct {
readonly issuer: AccountId32;
readonly metadata: Bytes;
@@ -3119,7 +3123,7 @@
readonly nftsCount: u32;
}
- /** @name RmrkTraitsNftNftInfo (383) */
+ /** @name RmrkTraitsNftNftInfo (384) */
interface RmrkTraitsNftNftInfo extends Struct {
readonly owner: RmrkTraitsNftAccountIdOrCollectionNftTuple;
readonly royalty: Option<RmrkTraitsNftRoyaltyInfo>;
@@ -3128,13 +3132,13 @@
readonly pending: bool;
}
- /** @name RmrkTraitsNftRoyaltyInfo (385) */
+ /** @name RmrkTraitsNftRoyaltyInfo (386) */
interface RmrkTraitsNftRoyaltyInfo extends Struct {
readonly recipient: AccountId32;
readonly amount: Permill;
}
- /** @name RmrkTraitsResourceResourceInfo (386) */
+ /** @name RmrkTraitsResourceResourceInfo (387) */
interface RmrkTraitsResourceResourceInfo extends Struct {
readonly id: u32;
readonly resource: RmrkTraitsResourceResourceTypes;
@@ -3142,26 +3146,26 @@
readonly pendingRemoval: bool;
}
- /** @name RmrkTraitsPropertyPropertyInfo (387) */
+ /** @name RmrkTraitsPropertyPropertyInfo (388) */
interface RmrkTraitsPropertyPropertyInfo extends Struct {
readonly key: Bytes;
readonly value: Bytes;
}
- /** @name RmrkTraitsBaseBaseInfo (388) */
+ /** @name RmrkTraitsBaseBaseInfo (389) */
interface RmrkTraitsBaseBaseInfo extends Struct {
readonly issuer: AccountId32;
readonly baseType: Bytes;
readonly symbol: Bytes;
}
- /** @name RmrkTraitsNftNftChild (389) */
+ /** @name RmrkTraitsNftNftChild (390) */
interface RmrkTraitsNftNftChild extends Struct {
readonly collectionId: u32;
readonly nftId: u32;
}
- /** @name PalletCommonError (391) */
+ /** @name PalletCommonError (392) */
interface PalletCommonError extends Enum {
readonly isCollectionNotFound: boolean;
readonly isMustBeTokenOwner: boolean;
@@ -3200,7 +3204,7 @@
readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'CantDestroyNotEmptyCollection' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal';
}
- /** @name PalletFungibleError (393) */
+ /** @name PalletFungibleError (394) */
interface PalletFungibleError extends Enum {
readonly isNotFungibleDataUsedToMintFungibleCollectionToken: boolean;
readonly isFungibleItemsHaveNoId: boolean;
@@ -3210,12 +3214,12 @@
readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
}
- /** @name PalletRefungibleItemData (394) */
+ /** @name PalletRefungibleItemData (395) */
interface PalletRefungibleItemData extends Struct {
readonly constData: Bytes;
}
- /** @name PalletRefungibleError (399) */
+ /** @name PalletRefungibleError (400) */
interface PalletRefungibleError extends Enum {
readonly isNotRefungibleDataUsedToMintFungibleCollectionToken: boolean;
readonly isWrongRefungiblePieces: boolean;
@@ -3225,12 +3229,12 @@
readonly type: 'NotRefungibleDataUsedToMintFungibleCollectionToken' | 'WrongRefungiblePieces' | 'RepartitionWhileNotOwningAllPieces' | 'RefungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
}
- /** @name PalletNonfungibleItemData (400) */
+ /** @name PalletNonfungibleItemData (401) */
interface PalletNonfungibleItemData extends Struct {
readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
}
- /** @name UpDataStructsPropertyScope (402) */
+ /** @name UpDataStructsPropertyScope (403) */
interface UpDataStructsPropertyScope extends Enum {
readonly isNone: boolean;
readonly isRmrk: boolean;
@@ -3238,7 +3242,7 @@
readonly type: 'None' | 'Rmrk' | 'Eth';
}
- /** @name PalletNonfungibleError (404) */
+ /** @name PalletNonfungibleError (405) */
interface PalletNonfungibleError extends Enum {
readonly isNotNonfungibleDataUsedToMintFungibleCollectionToken: boolean;
readonly isNonfungibleItemsHaveNoAmount: boolean;
@@ -3246,7 +3250,7 @@
readonly type: 'NotNonfungibleDataUsedToMintFungibleCollectionToken' | 'NonfungibleItemsHaveNoAmount' | 'CantBurnNftWithChildren';
}
- /** @name PalletStructureError (405) */
+ /** @name PalletStructureError (406) */
interface PalletStructureError extends Enum {
readonly isOuroborosDetected: boolean;
readonly isDepthLimit: boolean;
@@ -3255,7 +3259,7 @@
readonly type: 'OuroborosDetected' | 'DepthLimit' | 'BreadthLimit' | 'TokenNotFound';
}
- /** @name PalletRmrkCoreError (406) */
+ /** @name PalletRmrkCoreError (407) */
interface PalletRmrkCoreError extends Enum {
readonly isCorruptedCollectionType: boolean;
readonly isRmrkPropertyKeyIsTooLong: boolean;
@@ -3279,7 +3283,7 @@
readonly type: 'CorruptedCollectionType' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'RmrkPropertyIsNotFound' | 'UnableToDecodeRmrkData' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'CannotRejectNonPendingNft' | 'ResourceNotPending' | 'NoAvailableResourceId';
}
- /** @name PalletRmrkEquipError (408) */
+ /** @name PalletRmrkEquipError (409) */
interface PalletRmrkEquipError extends Enum {
readonly isPermissionError: boolean;
readonly isNoAvailableBaseId: boolean;
@@ -3291,7 +3295,7 @@
readonly type: 'PermissionError' | 'NoAvailableBaseId' | 'NoAvailablePartId' | 'BaseDoesntExist' | 'NeedsDefaultThemeFirst' | 'PartDoesntExist' | 'NoEquippableOnFixedPart';
}
- /** @name PalletAppPromotionError (410) */
+ /** @name PalletAppPromotionError (412) */
interface PalletAppPromotionError extends Enum {
readonly isAdminNotSet: boolean;
readonly isNoPermission: boolean;
@@ -3300,7 +3304,7 @@
readonly type: 'AdminNotSet' | 'NoPermission' | 'NotSufficientFounds' | 'InvalidArgument';
}
- /** @name PalletEvmError (413) */
+ /** @name PalletEvmError (415) */
interface PalletEvmError extends Enum {
readonly isBalanceLow: boolean;
readonly isFeeOverflow: boolean;
@@ -3311,7 +3315,7 @@
readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce';
}
- /** @name FpRpcTransactionStatus (416) */
+ /** @name FpRpcTransactionStatus (418) */
interface FpRpcTransactionStatus extends Struct {
readonly transactionHash: H256;
readonly transactionIndex: u32;
@@ -3322,10 +3326,10 @@
readonly logsBloom: EthbloomBloom;
}
- /** @name EthbloomBloom (418) */
+ /** @name EthbloomBloom (420) */
interface EthbloomBloom extends U8aFixed {}
- /** @name EthereumReceiptReceiptV3 (420) */
+ /** @name EthereumReceiptReceiptV3 (422) */
interface EthereumReceiptReceiptV3 extends Enum {
readonly isLegacy: boolean;
readonly asLegacy: EthereumReceiptEip658ReceiptData;
@@ -3336,7 +3340,7 @@
readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
}
- /** @name EthereumReceiptEip658ReceiptData (421) */
+ /** @name EthereumReceiptEip658ReceiptData (423) */
interface EthereumReceiptEip658ReceiptData extends Struct {
readonly statusCode: u8;
readonly usedGas: U256;
@@ -3344,14 +3348,14 @@
readonly logs: Vec<EthereumLog>;
}
- /** @name EthereumBlock (422) */
+ /** @name EthereumBlock (424) */
interface EthereumBlock extends Struct {
readonly header: EthereumHeader;
readonly transactions: Vec<EthereumTransactionTransactionV2>;
readonly ommers: Vec<EthereumHeader>;
}
- /** @name EthereumHeader (423) */
+ /** @name EthereumHeader (425) */
interface EthereumHeader extends Struct {
readonly parentHash: H256;
readonly ommersHash: H256;
@@ -3370,24 +3374,24 @@
readonly nonce: EthereumTypesHashH64;
}
- /** @name EthereumTypesHashH64 (424) */
+ /** @name EthereumTypesHashH64 (426) */
interface EthereumTypesHashH64 extends U8aFixed {}
- /** @name PalletEthereumError (429) */
+ /** @name PalletEthereumError (431) */
interface PalletEthereumError extends Enum {
readonly isInvalidSignature: boolean;
readonly isPreLogExists: boolean;
readonly type: 'InvalidSignature' | 'PreLogExists';
}
- /** @name PalletEvmCoderSubstrateError (430) */
+ /** @name PalletEvmCoderSubstrateError (432) */
interface PalletEvmCoderSubstrateError extends Enum {
readonly isOutOfGas: boolean;
readonly isOutOfFund: boolean;
readonly type: 'OutOfGas' | 'OutOfFund';
}
- /** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr (431) */
+ /** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr (433) */
interface UpDataStructsSponsorshipStateBasicCrossAccountIdRepr extends Enum {
readonly isDisabled: boolean;
readonly isUnconfirmed: boolean;
@@ -3397,7 +3401,7 @@
readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed';
}
- /** @name PalletEvmContractHelpersSponsoringModeT (432) */
+ /** @name PalletEvmContractHelpersSponsoringModeT (434) */
interface PalletEvmContractHelpersSponsoringModeT extends Enum {
readonly isDisabled: boolean;
readonly isAllowlisted: boolean;
@@ -3405,21 +3409,21 @@
readonly type: 'Disabled' | 'Allowlisted' | 'Generous';
}
- /** @name PalletEvmContractHelpersError (434) */
+ /** @name PalletEvmContractHelpersError (436) */
interface PalletEvmContractHelpersError extends Enum {
readonly isNoPermission: boolean;
readonly isNoPendingSponsor: boolean;
readonly type: 'NoPermission' | 'NoPendingSponsor';
}
- /** @name PalletEvmMigrationError (435) */
+ /** @name PalletEvmMigrationError (437) */
interface PalletEvmMigrationError extends Enum {
readonly isAccountNotEmpty: boolean;
readonly isAccountIsNotMigrating: boolean;
readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating';
}
- /** @name SpRuntimeMultiSignature (437) */
+ /** @name SpRuntimeMultiSignature (439) */
interface SpRuntimeMultiSignature extends Enum {
readonly isEd25519: boolean;
readonly asEd25519: SpCoreEd25519Signature;
@@ -3430,34 +3434,34 @@
readonly type: 'Ed25519' | 'Sr25519' | 'Ecdsa';
}
- /** @name SpCoreEd25519Signature (438) */
+ /** @name SpCoreEd25519Signature (440) */
interface SpCoreEd25519Signature extends U8aFixed {}
- /** @name SpCoreSr25519Signature (440) */
+ /** @name SpCoreSr25519Signature (442) */
interface SpCoreSr25519Signature extends U8aFixed {}
- /** @name SpCoreEcdsaSignature (441) */
+ /** @name SpCoreEcdsaSignature (443) */
interface SpCoreEcdsaSignature extends U8aFixed {}
- /** @name FrameSystemExtensionsCheckSpecVersion (444) */
+ /** @name FrameSystemExtensionsCheckSpecVersion (446) */
type FrameSystemExtensionsCheckSpecVersion = Null;
- /** @name FrameSystemExtensionsCheckGenesis (445) */
+ /** @name FrameSystemExtensionsCheckGenesis (447) */
type FrameSystemExtensionsCheckGenesis = Null;
- /** @name FrameSystemExtensionsCheckNonce (448) */
+ /** @name FrameSystemExtensionsCheckNonce (450) */
interface FrameSystemExtensionsCheckNonce extends Compact<u32> {}
- /** @name FrameSystemExtensionsCheckWeight (449) */
+ /** @name FrameSystemExtensionsCheckWeight (451) */
type FrameSystemExtensionsCheckWeight = Null;
- /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (450) */
+ /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (452) */
interface PalletTemplateTransactionPaymentChargeTransactionPayment extends Compact<u128> {}
- /** @name OpalRuntimeRuntime (451) */
+ /** @name OpalRuntimeRuntime (453) */
type OpalRuntimeRuntime = Null;
- /** @name PalletEthereumFakeTransactionFinalizer (452) */
+ /** @name PalletEthereumFakeTransactionFinalizer (454) */
type PalletEthereumFakeTransactionFinalizer = Null;
} // declare module