difftreelog
fix clippy warnings
in: master
36 files changed
node/cli/src/chain_spec.rsdiffbeforeafterboth--- a/node/cli/src/chain_spec.rs
+++ b/node/cli/src/chain_spec.rs
@@ -110,7 +110,7 @@
/// Helper function to generate a crypto pair from seed
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
- TPublic::Pair::from_string(&format!("//{}", seed), None)
+ TPublic::Pair::from_string(&format!("//{seed}"), None)
.expect("static values are valid; qed")
.public()
}
node/cli/src/command.rsdiffbeforeafterboth--- a/node/cli/src/command.rs
+++ b/node/cli/src/command.rs
@@ -83,7 +83,7 @@
"" | "local" => Box::new(chain_spec::local_testnet_config()),
path => {
let path = std::path::PathBuf::from(path);
- let chain_spec = Box::new(chain_spec::OpalChainSpec::from_json_file(path.clone())?)
+ let chain_spec = Box::new(chain_spec::OpalChainSpec::from_json_file(path)?)
as Box<dyn sc_service::ChainSpec>;
match chain_spec.runtime_id() {
@@ -352,7 +352,7 @@
&polkadot_cli,
config.tokio_handle.clone(),
)
- .map_err(|err| format!("Relay chain argument error: {}", err))?;
+ .map_err(|err| format!("Relay chain argument error: {err}"))?;
cmd.run(config, polkadot_config)
})
@@ -464,7 +464,7 @@
runner.run_node_until_exit(|config| async move {
let hwbench = if !cli.no_hardware_benchmarks {
config.database.path().map(|database_path| {
- let _ = std::fs::create_dir_all(&database_path);
+ let _ = std::fs::create_dir_all(database_path);
sc_sysinfo::gather_hwbench(Some(database_path))
})
} else {
@@ -513,7 +513,7 @@
let state_version =
RelayChainCli::native_runtime_version(&config.chain_spec).state_version();
let block: Block = generate_genesis_block(&*config.chain_spec, state_version)
- .map_err(|e| format!("{:?}", e))?;
+ .map_err(|e| format!("{e:?}"))?;
let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode()));
let genesis_hash = format!("0x{:?}", HexDisplay::from(&block.header().hash().0));
@@ -522,7 +522,7 @@
&polkadot_cli,
config.tokio_handle.clone(),
)
- .map_err(|err| format!("Relay chain argument error: {}", err))?;
+ .map_err(|err| format!("Relay chain argument error: {err}"))?;
info!("Parachain id: {:?}", para_id);
info!("Parachain Account: {}", parachain_account);
node/cli/src/service.rsdiffbeforeafterboth--- a/node/cli/src/service.rs
+++ b/node/cli/src/service.rs
@@ -698,7 +698,7 @@
{
let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;
- let block_import = ParachainBlockImport::new(client.clone(), backend.clone());
+ let block_import = ParachainBlockImport::new(client.clone(), backend);
cumulus_client_consensus_aura::import_queue::<
sp_consensus_aura::sr25519::AuthorityPair,
@@ -709,7 +709,7 @@
_,
>(cumulus_client_consensus_aura::ImportQueueParams {
block_import,
- client: client.clone(),
+ client,
create_inherent_data_providers: move |_, _| async move {
let time = sp_timestamp::InherentDataProvider::from_system_time();
@@ -787,7 +787,7 @@
telemetry.clone(),
);
- let block_import = ParachainBlockImport::new(client.clone(), backend.clone());
+ let block_import = ParachainBlockImport::new(client.clone(), backend);
Ok(AuraConsensus::build::<
sp_consensus_aura::sr25519::AuthorityPair,
@@ -864,7 +864,7 @@
ExecutorDispatch: NativeExecutionDispatch + 'static,
{
Ok(sc_consensus_manual_seal::import_queue(
- Box::new(client.clone()),
+ Box::new(client),
&task_manager.spawn_essential_handle(),
config.prometheus_registry(),
))
@@ -956,7 +956,7 @@
let collator = config.role.is_authority();
- let select_chain = maybe_select_chain.clone();
+ let select_chain = maybe_select_chain;
if collator {
let block_import =
node/rpc/src/lib.rsdiffbeforeafterboth--- a/node/rpc/src/lib.rs
+++ b/node/rpc/src/lib.rs
@@ -289,7 +289,7 @@
io.merge(
Net::new(
client.clone(),
- network.clone(),
+ network,
// Whether to format the `peer_count` response as Hex (default) or not.
true,
)
pallets/app-promotion/src/lib.rsdiffbeforeafterboth--- a/pallets/app-promotion/src/lib.rs
+++ b/pallets/app-promotion/src/lib.rs
@@ -296,7 +296,7 @@
if !block_pending.is_empty() {
block_pending.into_iter().for_each(|(staker, amount)| {
- Self::get_frozen_balance(&staker).map(|b| {
+ if let Some(b) = Self::get_frozen_balance(&staker) {
let new_state = b.checked_sub(&amount).unwrap_or_default();
// In this case, setting a new state for the frozen funds cannot fail
@@ -305,7 +305,7 @@
// that we cannot (in the current implementation) unfreeze more funds
// than were originally frozen by the pallet. Either way, `on_initialize()` cannot fail.
Self::set_freeze_unchecked(&staker, new_state);
- });
+ };
});
}
@@ -598,8 +598,8 @@
// this value is set for the stakers to whom the recalculation will be performed
let next_recalc_block = current_recalc_block + config.recalculation_interval;
- let mut storage_iterator = Self::get_next_calculated_key()
- .map_or(Staked::<T>::iter(), |key| Staked::<T>::iter_from(key));
+ let storage_iterator =
+ Self::get_next_calculated_key().map_or(Staked::<T>::iter(), Staked::<T>::iter_from);
PreviousCalculatedRecord::<T>::set(None);
@@ -658,10 +658,8 @@
// stakers_number - keeps the remaining number of iterations (staker addresses to handle)
// next_recalc_block_for_stake - is taken from the state and stores the starting relay block from which reward should be paid out
// income_acc - stores the reward amount to pay to the staker address (accumulates over all address stake records)
- while let Some((
- (current_id, staked_block),
- (amount, next_recalc_block_for_stake),
- )) = storage_iterator.next()
+ for ((current_id, staked_block), (amount, next_recalc_block_for_stake)) in
+ storage_iterator
{
// last_id is not equal current_id when we switch to handling a new staker address
// or just start handling the very first address. In the latter case last_id will be None and
@@ -859,11 +857,11 @@
if acc_amount < balance_per_block {
let res = (block, balance_per_block - acc_amount);
acc_amount = <BalanceOf<T>>::default();
- return Some(res);
+ Some(res)
} else {
acc_amount -= balance_per_block;
will_deleted_stakes_count += 1;
- return Some((block, <BalanceOf<T>>::default()));
+ Some((block, <BalanceOf<T>>::default()))
}
})
.collect::<Vec<_>>();
@@ -926,7 +924,7 @@
if amount.is_zero() {
<<T as Config>::Currency as MutateFreeze<T::AccountId>>::thaw(
&T::FreezeIdentifier::get(),
- &staker,
+ staker,
)
} else {
<<T as Config>::Currency as MutateFreeze<T::AccountId>>::set_freeze(
@@ -1026,10 +1024,10 @@
) {
let income = Self::calculate_income(base, iters);
- base.checked_add(&income).map(|res| {
+ if let Some(res) = base.checked_add(&income) {
<Staked<T>>::insert((staker, staked_block), (res, next_recalc_block));
*income_acc += income;
- });
+ };
}
fn calculate_income<I>(base: I, iters: u32) -> I
pallets/app-promotion/src/types.rsdiffbeforeafterboth--- a/pallets/app-promotion/src/types.rs
+++ b/pallets/app-promotion/src/types.rs
@@ -149,16 +149,16 @@
Self {
recalculation_interval: config
.recalculation_interval
- .unwrap_or_else(|| T::RecalculationInterval::get()),
+ .unwrap_or_else(T::RecalculationInterval::get),
pending_interval: config
.pending_interval
- .unwrap_or_else(|| T::PendingInterval::get()),
+ .unwrap_or_else(T::PendingInterval::get),
interval_income: config
.interval_income
- .unwrap_or_else(|| T::IntervalIncome::get()),
+ .unwrap_or_else(T::IntervalIncome::get),
max_stakers_per_calculation: config
.max_stakers_per_calculation
- .unwrap_or_else(|| MAX_NUMBER_PAYOUTS),
+ .unwrap_or(MAX_NUMBER_PAYOUTS),
}
}
}
pallets/balances-adapter/src/lib.rsdiffbeforeafterboth--- a/pallets/balances-adapter/src/lib.rs
+++ b/pallets/balances-adapter/src/lib.rs
@@ -31,6 +31,12 @@
}
}
+impl<T: Config> Default for NativeFungibleHandle<T> {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
impl<T: Config> WithRecorder<T> for NativeFungibleHandle<T> {
fn recorder(&self) -> &pallet_evm_coder_substrate::SubstrateRecorder<T> {
&self.0
pallets/common/src/eth.rsdiffbeforeafterboth--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -136,7 +136,7 @@
fn try_from(from: up_data_structs::Property) -> Result<Self, Self::Error> {
let key = evm_coder::types::String::from_utf8(from.key.into())
- .map_err(|e| Self::Error::Revert(format!("utf8 conversion error: {}", e)))?;
+ .map_err(|e| Self::Error::Revert(format!("utf8 conversion error: {e}")))?;
let value = evm_coder::types::Bytes(from.value.to_vec());
Ok(Property { key, value })
}
@@ -201,10 +201,7 @@
pub fn new(field: CollectionLimitField, value: Option<u32>) -> Self {
Self {
field,
- value: match value {
- Some(value) => Some(value.into()),
- None => None,
- },
+ value: value.map(|value| value.into()),
}
}
/// Whether the field contains a value.
@@ -222,8 +219,7 @@
.ok_or::<Self::Error>("can't convert `None` value to boolean".into())?;
let value = Some(value.try_into().map_err(|error| {
Self::Error::Revert(format!(
- "can't convert value to u32 \"{}\" because: \"{error}\"",
- value
+ "can't convert value to u32 \"{value}\" because: \"{error}\""
))
})?);
@@ -249,10 +245,8 @@
limits.sponsored_data_size = value;
}
CollectionLimitField::SponsoredDataRateLimit => {
- limits.sponsored_data_rate_limit = match value {
- Some(value) => Some(up_data_structs::SponsoringRateLimit::Blocks(value)),
- None => None,
- };
+ limits.sponsored_data_rate_limit =
+ value.map(up_data_structs::SponsoringRateLimit::Blocks);
}
CollectionLimitField::TokenLimit => {
limits.token_limit = value;
@@ -454,9 +448,9 @@
}
}
-impl Into<up_data_structs::AccessMode> for AccessMode {
- fn into(self) -> up_data_structs::AccessMode {
- match self {
+impl From<AccessMode> for up_data_structs::AccessMode {
+ fn from(value: AccessMode) -> Self {
+ match value {
AccessMode::Normal => up_data_structs::AccessMode::Normal,
AccessMode::AllowList => up_data_structs::AccessMode::AllowList,
}
pallets/evm-coder-substrate/src/lib.rsdiffbeforeafterboth--- a/pallets/evm-coder-substrate/src/lib.rs
+++ b/pallets/evm-coder-substrate/src/lib.rs
@@ -260,9 +260,9 @@
message: Some(msg), ..
}) => ExError::Revert(msg.into()),
DispatchError::Module(ModuleError { index, error, .. }) => {
- ExError::Revert(format!("error {:?} in pallet {}", error, index))
+ ExError::Revert(format!("error {error:?} in pallet {index}"))
}
- e => ExError::Revert(format!("substrate error: {:?}", e)),
+ e => ExError::Revert(format!("substrate error: {e:?}")),
}
}
pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -184,10 +184,9 @@
/// @param contractAddress The contract for which a sponsor is requested.
/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
fn sponsor(&self, contract_address: Address) -> Result<Option<eth::CrossAddress>> {
- Ok(match Pallet::<T>::get_sponsor(contract_address) {
- Some(ref value) => Some(eth::CrossAddress::from_sub_cross_account::<T>(value)),
- None => None,
- })
+ Ok(Pallet::<T>::get_sponsor(contract_address)
+ .as_ref()
+ .map(eth::CrossAddress::from_sub_cross_account::<T>))
}
/// Check tat contract has confirmed sponsor.
@@ -275,7 +274,7 @@
self.recorder().consume_sstore()?;
<Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;
- <Pallet<T>>::set_sponsoring_fee_limit(contract_address, fee_limit.into())
+ <Pallet<T>>::set_sponsoring_fee_limit(contract_address, fee_limit)
.map_err(dispatch_to_evm::<T>)?;
Ok(())
}
pallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/lib.rs
+++ b/pallets/evm-contract-helpers/src/lib.rs
@@ -376,7 +376,7 @@
<SponsoringMode<T>>::get(contract)
.or_else(|| {
#[allow(deprecated)]
- <SelfSponsoring<T>>::get(contract).then(|| SponsoringModeT::Allowlisted)
+ <SelfSponsoring<T>>::get(contract).then_some(SponsoringModeT::Allowlisted)
})
.unwrap_or_default()
}
@@ -410,7 +410,7 @@
/// Is user added to allowlist, or he is owner of specified contract
pub fn allowed(contract: H160, user: H160) -> bool {
- <Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(&contract) == user
+ <Allowlist<T>>::get(contract, user) || <Owner<T>>::get(contract) == user
}
/// Toggle contract allowlist access
@@ -425,7 +425,7 @@
/// Throw error if user is not allowed to reconfigure target contract
pub fn ensure_owner(contract: H160, user: H160) -> DispatchResult {
- ensure!(<Owner<T>>::get(&contract) == user, Error::<T>::NoPermission);
+ ensure!(<Owner<T>>::get(contract) == user, Error::<T>::NoPermission);
Ok(())
}
}
pallets/evm-migration/src/lib.rsdiffbeforeafterboth--- a/pallets/evm-migration/src/lib.rs
+++ b/pallets/evm-migration/src/lib.rs
@@ -78,7 +78,7 @@
pub fn begin(origin: OriginFor<T>, address: H160) -> DispatchResult {
ensure_root(origin)?;
ensure!(
- <PalletEvm<T>>::is_account_empty(&address) && !<MigrationPending<T>>::get(&address),
+ <PalletEvm<T>>::is_account_empty(&address) && !<MigrationPending<T>>::get(address),
<Error<T>>::AccountNotEmpty,
);
@@ -97,12 +97,12 @@
) -> DispatchResult {
ensure_root(origin)?;
ensure!(
- <MigrationPending<T>>::get(&address),
+ <MigrationPending<T>>::get(address),
<Error<T>>::AccountIsNotMigrating,
);
for (k, v) in data {
- <pallet_evm::AccountStorages<T>>::insert(&address, k, v);
+ <pallet_evm::AccountStorages<T>>::insert(address, k, v);
}
Ok(())
}
@@ -115,11 +115,11 @@
pub fn finish(origin: OriginFor<T>, address: H160, code: Vec<u8>) -> DispatchResult {
ensure_root(origin)?;
ensure!(
- <MigrationPending<T>>::get(&address),
+ <MigrationPending<T>>::get(address),
<Error<T>>::AccountIsNotMigrating,
);
- <pallet_evm::AccountCodes<T>>::insert(&address, code);
+ <pallet_evm::AccountCodes<T>>::insert(address, code);
<MigrationPending<T>>::remove(address);
Ok(())
}
@@ -166,7 +166,7 @@
pub struct OnMethodCall<T>(PhantomData<T>);
impl<T: Config> pallet_evm::OnMethodCall<T> for OnMethodCall<T> {
fn is_reserved(contract: &H160) -> bool {
- <MigrationPending<T>>::get(&contract)
+ <MigrationPending<T>>::get(contract)
}
fn is_used(_contract: &H160) -> bool {
pallets/foreign-assets/src/impl_fungibles.rsdiffbeforeafterboth--- a/pallets/foreign-assets/src/impl_fungibles.rs
+++ b/pallets/foreign-assets/src/impl_fungibles.rs
@@ -333,7 +333,7 @@
&Value::new(0),
)?;
- Ok(amount.into())
+ Ok(amount)
}
}
}
pallets/foreign-assets/src/lib.rsdiffbeforeafterboth--- a/pallets/foreign-assets/src/lib.rs
+++ b/pallets/foreign-assets/src/lib.rs
@@ -161,7 +161,7 @@
fn get_currency_id(multi_location: MultiLocation) -> Option<CurrencyId> {
log::trace!(target: "fassets::get_currency_id", "call");
- Pallet::<T>::location_to_currency_ids(multi_location).map(|id| AssetIds::ForeignAssetId(id))
+ Pallet::<T>::location_to_currency_ids(multi_location).map(AssetIds::ForeignAssetId)
}
}
@@ -378,7 +378,7 @@
foreign_asset_id,
|maybe_location| -> DispatchResult {
ensure!(maybe_location.is_none(), Error::<T>::MultiLocationExisted);
- *maybe_location = Some(location.clone());
+ *maybe_location = Some(*location);
AssetMetadatas::<T>::try_mutate(
AssetIds::ForeignAssetId(foreign_asset_id),
@@ -422,7 +422,7 @@
// modify location
if location != old_multi_locations {
- LocationToCurrencyIds::<T>::remove(old_multi_locations.clone());
+ LocationToCurrencyIds::<T>::remove(*old_multi_locations);
LocationToCurrencyIds::<T>::try_mutate(
location,
|maybe_currency_ids| -> DispatchResult {
@@ -437,7 +437,7 @@
)?;
}
*maybe_asset_metadatas = Some(metadata.clone());
- *old_multi_locations = location.clone();
+ *old_multi_locations = *location;
Ok(())
},
)
pallets/identity/src/types.rsdiffbeforeafterboth--- a/pallets/identity/src/types.rs
+++ b/pallets/identity/src/types.rs
@@ -104,7 +104,7 @@
Data::Raw(ref x) => {
let l = x.len().min(32);
let mut r = vec![l as u8 + 1; l + 1];
- r[1..].copy_from_slice(&x[..l as usize]);
+ r[1..].copy_from_slice(&x[..l]);
r
}
Data::BlakeTwo256(ref h) => once(34u8).chain(h.iter().cloned()).collect(),
@@ -287,7 +287,7 @@
fn decode<I: codec::Input>(input: &mut I) -> sp_std::result::Result<Self, codec::Error> {
let field = u64::decode(input)?;
Ok(Self(
- <BitFlags<IdentityField>>::from_bits(field as u64).map_err(|_| "invalid value")?,
+ <BitFlags<IdentityField>>::from_bits(field).map_err(|_| "invalid value")?,
))
}
}
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -20,6 +20,8 @@
//! Method implementations are mostly doing parameter conversion and calling Nonfungible Pallet methods.
extern crate alloc;
+
+use alloc::string::ToString;
use core::{
char::{REPLACEMENT_CHARACTER, decode_utf16},
convert::TryInto,
@@ -356,8 +358,7 @@
.transpose()
.map_err(|e| {
Error::Revert(alloc::format!(
- "Can not convert value \"baseURI\" to string with error \"{}\"",
- e
+ "Can not convert value \"baseURI\" to string with error \"{e}\""
))
})?;
@@ -675,7 +676,7 @@
.try_into()
.map_err(|_| "token uri is too long")?,
})
- .map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;
+ .map_err(|e| Error::Revert(alloc::format!("Can't add property: {e:?}")))?;
<Pallet<T>>::create_item(
self,
@@ -717,7 +718,7 @@
.map(Clone::clone)
.ok_or_else(|| {
let key = String::from_utf8(key.clone().into_inner()).unwrap_or_default();
- Error::Revert(alloc::format!("No permission for key {}", key))
+ Error::Revert(alloc::format!("No permission for key {key}"))
})?;
Ok(a)
}
@@ -752,14 +753,14 @@
/// @param tokenId Id for the token.
#[solidity(hide)]
fn cross_owner_of(&self, token_id: U256) -> Result<eth::CrossAddress> {
- Self::owner_of_cross(&self, token_id)
+ Self::owner_of_cross(self, token_id)
}
/// Returns the owner (in cross format) of the token.
///
/// @param tokenId Id for the token.
fn owner_of_cross(&self, token_id: U256) -> Result<eth::CrossAddress> {
- Self::token_owner(&self, token_id.try_into()?)
+ Self::token_owner(self, token_id.try_into()?)
.map(|o| eth::CrossAddress::from_sub_cross_account::<T>(&o))
.map_err(|_| Error::Revert("token not found".into()))
}
@@ -789,7 +790,7 @@
.collect::<Result<Vec<_>>>()?;
<Self as CommonCollectionOperations<T>>::token_properties(
- &self,
+ self,
token_id.try_into()?,
if keys.is_empty() { None } else { Some(keys) },
)
@@ -1021,7 +1022,7 @@
.try_into()
.map_err(|_| "token uri is too long")?,
})
- .map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;
+ .map_err(|e| Error::Revert(alloc::format!("Can't add property: {e:?}")))?;
data.push(CreateItemData::<T> {
properties,
@@ -1056,7 +1057,7 @@
.map(eth::Property::try_into)
.collect::<Result<Vec<_>>>()?
.try_into()
- .map_err(|_| Error::Revert(alloc::format!("too many properties")))?;
+ .map_err(|_| Error::Revert("too many properties".to_string()))?;
let caller = T::CrossAccountId::from_eth(caller);
pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -166,10 +166,7 @@
#[pallet::config]
pub trait Config:
- frame_system::Config
- + pallet_common::Config
- + pallet_structure::Config
- + pallet_evm::Config
+ frame_system::Config + pallet_common::Config + pallet_structure::Config + pallet_evm::Config
{
type WeightInfo: WeightInfo;
}
@@ -860,13 +857,7 @@
<PalletStructure<T>>::unnest_if_nested(&token_data.owner, collection.id, token);
- <TokenData<T>>::insert(
- (collection.id, token),
- ItemData {
- owner: to.clone(),
- ..token_data
- },
- );
+ <TokenData<T>>::insert((collection.id, token), ItemData { owner: to.clone() });
if let Some(balance_to) = balance_to {
// from != to
pallets/refungible/src/erc.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -21,6 +21,7 @@
extern crate alloc;
+use alloc::string::ToString;
use core::{
char::{REPLACEMENT_CHARACTER, decode_utf16},
convert::TryInto,
@@ -353,8 +354,7 @@
.transpose()
.map_err(|e| {
Error::Revert(alloc::format!(
- "Can not convert value \"baseURI\" to string with error \"{}\"",
- e
+ "Can not convert value \"baseURI\" to string with error \"{e}\""
))
})?;
@@ -482,8 +482,8 @@
.recorder
.weight_calls_budget(<StructureWeight<T>>::find_parent());
- let balance = balance(&self, token, &from)?;
- ensure_single_owner(&self, token, balance)?;
+ let balance = balance(self, token, &from)?;
+ ensure_single_owner(self, token, balance)?;
<Pallet<T>>::transfer_from(self, &caller, &from, &to, token, balance, &budget)
.map_err(dispatch_to_evm::<T>)?;
@@ -575,8 +575,8 @@
let caller = T::CrossAccountId::from_eth(caller);
let token = token_id.try_into()?;
- let balance = balance(&self, token, &caller)?;
- ensure_single_owner(&self, token, balance)?;
+ let balance = balance(self, token, &caller)?;
+ ensure_single_owner(self, token, balance)?;
<Pallet<T>>::burn(self, &caller, token, balance).map_err(dispatch_to_evm::<T>)?;
Ok(())
@@ -622,7 +622,7 @@
return Err("item id should be next".into());
}
- let users = [(to.clone(), 1)]
+ let users = [(to, 1)]
.into_iter()
.collect::<BTreeMap<_, _>>()
.try_into()
@@ -706,9 +706,9 @@
.try_into()
.map_err(|_| "token uri is too long")?,
})
- .map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;
+ .map_err(|e| Error::Revert(alloc::format!("Can't add property: {e:?}")))?;
- let users = [(to.clone(), 1)]
+ let users = [(to, 1)]
.into_iter()
.collect::<BTreeMap<_, _>>()
.try_into()
@@ -750,7 +750,7 @@
.map(Clone::clone)
.ok_or_else(|| {
let key = String::from_utf8(key.clone().into_inner()).unwrap_or_default();
- Error::Revert(alloc::format!("No permission for key {}", key))
+ Error::Revert(alloc::format!("No permission for key {key}"))
})?;
Ok(a)
}
@@ -785,14 +785,14 @@
/// @param tokenId Id for the token.
#[solidity(hide)]
fn cross_owner_of(&self, token_id: U256) -> Result<eth::CrossAddress> {
- Self::owner_of_cross(&self, token_id)
+ Self::owner_of_cross(self, token_id)
}
/// Returns the owner (in cross format) of the token.
///
/// @param tokenId Id for the token.
fn owner_of_cross(&self, token_id: U256) -> Result<eth::CrossAddress> {
- Self::token_owner(&self, token_id.try_into()?)
+ Self::token_owner(self, token_id.try_into()?)
.map(|o| eth::CrossAddress::from_sub_cross_account::<T>(&o))
.or_else(|err| match err {
TokenOwnerError::NotFound => Err(Error::Revert("token not found".into())),
@@ -827,7 +827,7 @@
.collect::<Result<Vec<_>>>()?;
<Self as CommonCollectionOperations<T>>::token_properties(
- &self,
+ self,
token_id.try_into()?,
if keys.is_empty() { None } else { Some(keys) },
)
@@ -1004,7 +1004,7 @@
}
expected_index = expected_index.checked_add(1).ok_or("item id overflow")?;
}
- let users = [(to.clone(), 1)]
+ let users = [(to, 1)]
.into_iter()
.collect::<BTreeMap<_, _>>()
.try_into()
@@ -1046,7 +1046,7 @@
.weight_calls_budget(<StructureWeight<T>>::find_parent());
let mut data = Vec::with_capacity(tokens.len());
- let users: BoundedBTreeMap<_, _, _> = [(to.clone(), 1)]
+ let users: BoundedBTreeMap<_, _, _> = [(to, 1)]
.into_iter()
.collect::<BTreeMap<_, _>>()
.try_into()
@@ -1067,7 +1067,7 @@
.try_into()
.map_err(|_| "token uri is too long")?,
})
- .map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;
+ .map_err(|e| Error::Revert(alloc::format!("Can't add property: {e:?}")))?;
let create_item_data = CreateItemData::<T> {
users: users.clone(),
@@ -1103,7 +1103,7 @@
.map(eth::Property::try_into)
.collect::<Result<Vec<_>>>()?
.try_into()
- .map_err(|_| Error::Revert(alloc::format!("too many properties")))?;
+ .map_err(|_| Error::Revert("too many properties".to_string()))?;
let caller = T::CrossAccountId::from_eth(caller);
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -1124,7 +1124,7 @@
if collection.ignores_token_restrictions(spender) {
return Ok(Self::compute_allowance_decrease(
- collection, token, from, &spender, amount,
+ collection, token, from, spender, amount,
));
}
@@ -1143,7 +1143,7 @@
return Ok(None);
}
- let allowance = Self::compute_allowance_decrease(collection, token, from, &spender, amount);
+ let allowance = Self::compute_allowance_decrease(collection, token, from, spender, amount);
if allowance.is_some() {
return Ok(allowance);
}
pallets/scheduler-v2/src/lib.rsdiffbeforeafterboth--- a/pallets/scheduler-v2/src/lib.rs
+++ b/pallets/scheduler-v2/src/lib.rs
@@ -969,7 +969,7 @@
call: ScheduledCall<T>,
) -> Result<TaskAddress<T::BlockNumber>, DispatchError> {
// ensure id it is unique
- if Lookup::<T>::contains_key(&id) {
+ if Lookup::<T>::contains_key(id) {
return Err(Error::<T>::FailedToSchedule.into());
}
pallets/structure/src/lib.rsdiffbeforeafterboth--- a/pallets/structure/src/lib.rs
+++ b/pallets/structure/src/lib.rs
@@ -280,7 +280,7 @@
) -> DispatchResultWithPostInfo {
let dispatch = T::CollectionDispatch::dispatch(collection)?;
let dispatch = dispatch.as_dyn();
- dispatch.burn_item_recursively(from.clone(), token, self_budget, breadth_budget)
+ dispatch.burn_item_recursively(from, token, self_budget, breadth_budget)
}
/// Check if `token` indirectly owned by `user`
@@ -396,7 +396,7 @@
account: &T::CrossAccountId,
action: impl FnOnce(&dyn CommonCollectionOperations<T>, TokenId) -> DispatchResult,
) -> DispatchResult {
- if is_collection(&account.as_eth()) {
+ if is_collection(account.as_eth()) {
fail!(<Error<T>>::CantNestTokenUnderCollection);
}
let Some((collection, token)) = T::CrossTokenAddressMapping::address_to_token(account) else {
pallets/unique/src/eth/mod.rsdiffbeforeafterboth--- a/pallets/unique/src/eth/mod.rs
+++ b/pallets/unique/src/eth/mod.rs
@@ -113,13 +113,9 @@
let collection_helpers_address =
T::CrossAccountId::from_eth(<T as pallet_common::Config>::ContractAddress::get());
- let collection_id = T::CollectionDispatch::create(
- caller.clone(),
- collection_helpers_address,
- data,
- Default::default(),
- )
- .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
+ let collection_id =
+ T::CollectionDispatch::create(caller, collection_helpers_address, data, Default::default())
+ .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
let address = pallet_common::eth::collection_id_to_address(collection_id);
Ok(address)
}
@@ -132,8 +128,7 @@
.expect("Collection creation price should be convertible to u128");
if value != creation_price {
return Err(format!(
- "Sent amount not equals to collection creation price ({0})",
- creation_price
+ "Sent amount not equals to collection creation price ({creation_price})",
)
.into());
}
@@ -383,8 +378,7 @@
map_eth_to_id(&collection_address)
.map(|id| id.0)
.ok_or(Error::Revert(format!(
- "failed to convert address {} into collectionId.",
- collection_address
+ "failed to convert address {collection_address} into collectionId."
)))
}
}
@@ -422,5 +416,5 @@
generate_stubgen!(collection_helper_iface, CollectionHelpersCall<()>, false);
fn error_field_too_long(feild: &str, bound: usize) -> Error {
- Error::Revert(format!("{} is too long. Max length is {}.", feild, bound))
+ Error::Revert(format!("{feild} is too long. Max length is {bound}."))
}
pallets/unique/src/lib.rsdiffbeforeafterboth--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -507,7 +507,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let new_owner = T::CrossAccountId::from_sub(new_owner);
let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
- target_collection.change_owner(sender, new_owner.clone())
+ target_collection.change_owner(sender, new_owner)
}
/// Add an admin to a collection.
@@ -667,7 +667,7 @@
/// * `owner`: Address of the initial owner of the item.
/// * `data`: Token data describing the item to store on chain.
#[pallet::call_index(11)]
- #[pallet::weight(T::CommonWeightInfo::create_item(&data))]
+ #[pallet::weight(T::CommonWeightInfo::create_item(data))]
pub fn create_item(
origin: OriginFor<T>,
collection_id: CollectionId,
@@ -701,7 +701,7 @@
/// * `owner`: Address of the initial owner of the tokens.
/// * `items_data`: Vector of data describing each item to be created.
#[pallet::call_index(12)]
- #[pallet::weight(T::CommonWeightInfo::create_multiple_items(&items_data))]
+ #[pallet::weight(T::CommonWeightInfo::create_multiple_items(items_data))]
pub fn create_multiple_items(
origin: OriginFor<T>,
collection_id: CollectionId,
@@ -889,7 +889,7 @@
/// * `collection_id`: ID of the collection to which the tokens would belong.
/// * `data`: Explicit item creation data.
#[pallet::call_index(18)]
- #[pallet::weight(T::CommonWeightInfo::create_multiple_items_ex(&data))]
+ #[pallet::weight(T::CommonWeightInfo::create_multiple_items_ex(data))]
pub fn create_multiple_items_ex(
origin: OriginFor<T>,
collection_id: CollectionId,
@@ -1313,7 +1313,7 @@
collection_id: CollectionId,
) -> DispatchResult {
let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
- target_collection.force_set_sponsor(sponsor.clone())
+ target_collection.force_set_sponsor(sponsor)
}
/// Force remove `sponsor` for `collection`.
primitives/data-structs/src/bounded.rsdiffbeforeafterboth--- a/primitives/data-structs/src/bounded.rs
+++ b/primitives/data-structs/src/bounded.rs
@@ -63,7 +63,7 @@
V: fmt::Debug,
{
use core::fmt::Debug;
- (&v as &Vec<V>).fmt(f)
+ (v as &Vec<V>).fmt(f)
}
#[cfg(feature = "serde1")]
@@ -114,7 +114,7 @@
V: fmt::Debug,
{
use core::fmt::Debug;
- (&v as &BTreeMap<K, V>).fmt(f)
+ (v as &BTreeMap<K, V>).fmt(f)
}
#[cfg(feature = "serde1")]
@@ -157,5 +157,5 @@
K: fmt::Debug + Ord,
{
use core::fmt::Debug;
- (&v as &BTreeSet<K>).fmt(f)
+ (v as &BTreeSet<K>).fmt(f)
}
primitives/data-structs/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//! # Primitives crate.18//!19//! This crate contains types, traits and constants.2021#![cfg_attr(not(feature = "std"), no_std)]2223use core::{24 convert::{TryFrom, TryInto},25 fmt,26 ops::Deref,27};28use frame_support::storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet};2930#[cfg(feature = "serde")]31use serde::{Serialize, Deserialize};3233use sp_core::U256;34use sp_runtime::{ArithmeticError, sp_std::prelude::Vec};35use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};36use bondrewd::Bitfields;37use frame_support::{BoundedVec, traits::ConstU32};38use derivative::Derivative;39use scale_info::TypeInfo;4041mod bondrewd_codec;42mod bounded;43pub mod budget;44pub mod mapping;45mod migration;4647/// Maximum of decimal points.48pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;4950/// Maximum pieces for refungible token.51pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;52pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;5354/// Maximum tokens for user.55pub const MAX_TOKEN_OWNERSHIP: u32 = if cfg!(not(feature = "limit-testing")) {56 100_00057} else {58 1059};6061/// Maximum for collections can be created.62pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {63 100_00064} else {65 1066};6768/// Maximum for various custom data of token.69pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {70 204871} else {72 1073};7475/// Maximum admins per collection.76pub const COLLECTION_ADMINS_LIMIT: u32 = 5;7778/// Maximum tokens per collection.79pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;8081/// Maximum tokens per account.82pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {83 1_000_00084} else {85 1086};8788/// Default timeout for transfer sponsoring NFT item.89pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;90/// Default timeout for transfer sponsoring fungible item.91pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;92/// Default timeout for transfer sponsoring refungible item.93pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;9495/// Default timeout for sponsored approving.96pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;9798// Schema limits99pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;100pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;101pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;102103// TODO: not used. Delete?104pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;105106/// Maximal length of a collection name.107pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;108109/// Maximal length of a collection description.110pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;111112/// Maximal length of a token prefix.113pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16;114115/// Maximal length of a property key.116pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256;117118/// Maximal length of a property value.119pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768;120121/// A maximum number of token properties.122pub const MAX_PROPERTIES_PER_ITEM: u32 = 64;123124/// Maximal lenght of extended property value.125pub const MAX_AUX_PROPERTY_VALUE_LENGTH: u32 = 2048;126127/// Maximum size for all collection properties.128pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960;129130/// Maximum size of all token properties.131pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768;132133/// How much items can be created per single134/// create_many call.135pub const MAX_ITEMS_PER_BATCH: u32 = 200;136137/// Used for limit bounded types of token custom data.138pub type CustomDataLimit = ConstU32<CUSTOM_DATA_LIMIT>;139140/// Collection id.141#[derive(142 Encode,143 Decode,144 PartialEq,145 Eq,146 PartialOrd,147 Ord,148 Clone,149 Copy,150 Debug,151 Default,152 TypeInfo,153 MaxEncodedLen,154)]155#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]156pub struct CollectionId(pub u32);157impl EncodeLike<u32> for CollectionId {}158impl EncodeLike<CollectionId> for u32 {}159160impl From<u32> for CollectionId {161 fn from(value: u32) -> Self {162 Self(value)163 }164}165166/// Token id.167#[derive(168 Encode,169 Decode,170 PartialEq,171 Eq,172 PartialOrd,173 Ord,174 Clone,175 Copy,176 Debug,177 Default,178 TypeInfo,179 MaxEncodedLen,180)]181#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]182pub struct TokenId(pub u32);183impl EncodeLike<u32> for TokenId {}184impl EncodeLike<TokenId> for u32 {}185186impl TokenId {187 /// Try to get next token id.188 ///189 /// If next id cause overflow, then [`ArithmeticError::Overflow`] returned.190 pub fn try_next(self) -> Result<TokenId, ArithmeticError> {191 self.0192 .checked_add(1)193 .ok_or(ArithmeticError::Overflow)194 .map(Self)195 }196}197198impl From<TokenId> for U256 {199 fn from(t: TokenId) -> Self {200 t.0.into()201 }202}203204impl TryFrom<U256> for TokenId {205 type Error = &'static str;206207 fn try_from(value: U256) -> Result<Self, Self::Error> {208 Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))209 }210}211212/// Token data.213#[struct_versioning::versioned(version = 2, upper)]214#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]215#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]216pub struct TokenData<CrossAccountId> {217 /// Properties of token.218 pub properties: Vec<Property>,219220 /// Token owner.221 pub owner: Option<CrossAccountId>,222223 /// Token pieces.224 #[version(2.., upper(0))]225 pub pieces: u128,226}227228// TODO: unused type229pub struct OverflowError;230impl From<OverflowError> for &'static str {231 fn from(_: OverflowError) -> Self {232 "overflow occured"233 }234}235236/// Alias for decimal points type.237pub type DecimalPoints = u8;238239/// Collection mode.240///241/// Collection can represent various types of tokens.242/// Each collection can contain only one type of tokens at a time.243/// This type helps to understand which tokens the collection contains.244#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]245#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]246pub enum CollectionMode {247 /// Non fungible tokens.248 NFT,249 /// Fungible tokens.250 Fungible(DecimalPoints),251 /// Refungible tokens.252 ReFungible,253}254255impl CollectionMode {256 /// Get collection mod as number.257 pub fn id(&self) -> u8 {258 match self {259 CollectionMode::NFT => 1,260 CollectionMode::Fungible(_) => 2,261 CollectionMode::ReFungible => 3,262 }263 }264}265266// TODO: unused trait267pub trait SponsoringResolve<AccountId, Call> {268 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;269}270271/// Access mode for some token operations.272#[derive(Encode, Decode, Eq, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]273#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]274pub enum AccessMode {275 /// Access grant for owner and admins. Used as default.276 Normal,277 /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.278 AllowList,279}280impl Default for AccessMode {281 fn default() -> Self {282 Self::Normal283 }284}285286// TODO: remove in future.287#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]288#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]289pub enum SchemaVersion {290 ImageURL,291 Unique,292}293impl Default for SchemaVersion {294 fn default() -> Self {295 Self::ImageURL296 }297}298299// TODO: unused type300#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]301#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]302pub struct Ownership<AccountId> {303 pub owner: AccountId,304 pub fraction: u128,305}306307/// The state of collection sponsorship.308#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]309#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]310pub enum SponsorshipState<AccountId> {311 /// The fees are applied to the transaction sender.312 Disabled,313 /// The sponsor is under consideration. Until the sponsor gives his consent,314 /// the fee will still be charged to sender.315 Unconfirmed(AccountId),316 /// Transactions are sponsored by specified account.317 Confirmed(AccountId),318}319320impl<AccountId> SponsorshipState<AccountId> {321 /// Get a sponsor of the collection who has confirmed his status.322 pub fn sponsor(&self) -> Option<&AccountId> {323 match self {324 Self::Confirmed(sponsor) => Some(sponsor),325 _ => None,326 }327 }328329 /// Get a sponsor of the collection who has pending or confirmed status.330 pub fn pending_sponsor(&self) -> Option<&AccountId> {331 match self {332 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),333 _ => None,334 }335 }336337 /// Whether the sponsorship is confirmed.338 pub fn confirmed(&self) -> bool {339 matches!(self, Self::Confirmed(_))340 }341}342343impl<T> Default for SponsorshipState<T> {344 fn default() -> Self {345 Self::Disabled346 }347}348349pub type CollectionName = BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>;350pub type CollectionDescription = BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>;351pub type CollectionTokenPrefix = BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>;352353#[derive(Bitfields, Clone, Copy, PartialEq, Eq, Debug, Default)]354#[bondrewd(enforce_bytes = 1)]355pub struct CollectionFlags {356 /// Tokens in foreign collections can be transferred, but not burnt357 #[bondrewd(bits = "0..1")]358 pub foreign: bool,359 /// Supports ERC721Metadata360 #[bondrewd(bits = "1..2")]361 pub erc721metadata: bool,362 /// External collections can't be managed using `unique` api363 #[bondrewd(bits = "7..8")]364 pub external: bool,365366 #[bondrewd(reserve, bits = "2..7")]367 pub reserved: u8,368}369bondrewd_codec!(CollectionFlags);370371/// Base structure for represent collection.372///373/// Used to provide basic functionality for all types of collections.374///375/// #### Note376/// Collection parameters, used in storage (see [`RpcCollection`] for the RPC version).377#[struct_versioning::versioned(version = 2, upper)]378#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]379pub struct Collection<AccountId> {380 /// Collection owner account.381 pub owner: AccountId,382383 /// Collection mode.384 pub mode: CollectionMode,385386 /// Access mode.387 #[version(..2)]388 pub access: AccessMode,389390 /// Collection name.391 pub name: CollectionName,392393 /// Collection description.394 pub description: CollectionDescription,395396 /// Token prefix.397 pub token_prefix: CollectionTokenPrefix,398399 #[version(..2)]400 pub mint_mode: bool,401402 #[version(..2)]403 pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,404405 #[version(..2)]406 pub schema_version: SchemaVersion,407408 /// The state of sponsorship of the collection.409 pub sponsorship: SponsorshipState<AccountId>,410411 /// Collection limits.412 pub limits: CollectionLimits,413414 /// Collection permissions.415 #[version(2.., upper(Default::default()))]416 pub permissions: CollectionPermissions,417418 #[version(2.., upper(Default::default()))]419 pub flags: CollectionFlags,420421 #[version(..2)]422 pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,423424 #[version(..2)]425 pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,426427 #[version(..2)]428 pub meta_update_permission: MetaUpdatePermission,429}430431#[derive(Debug, Encode, Decode, Clone, PartialEq, TypeInfo)]432#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]433pub struct RpcCollectionFlags {434 /// Is collection is foreign.435 pub foreign: bool,436 /// Collection supports ERC721Metadata.437 pub erc721metadata: bool,438}439440/// Collection parameters, used in RPC calls (see [`Collection`] for the storage version).441#[struct_versioning::versioned(version = 2, upper)]442#[derive(Debug, Encode, Decode, Clone, PartialEq, TypeInfo)]443#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]444pub struct RpcCollection<AccountId> {445 /// Collection owner account.446 pub owner: AccountId,447448 /// Collection mode.449 pub mode: CollectionMode,450451 /// Collection name.452 pub name: Vec<u16>,453454 /// Collection description.455 pub description: Vec<u16>,456457 /// Token prefix.458 pub token_prefix: Vec<u8>,459460 /// The state of sponsorship of the collection.461 pub sponsorship: SponsorshipState<AccountId>,462463 /// Collection limits.464 pub limits: CollectionLimits,465466 /// Collection permissions.467 pub permissions: CollectionPermissions,468469 /// Token property permissions.470 pub token_property_permissions: Vec<PropertyKeyPermission>,471472 /// Collection properties.473 pub properties: Vec<Property>,474475 /// Is collection read only.476 pub read_only: bool,477478 /// Extra collection flags479 #[version(2.., upper(RpcCollectionFlags {foreign: false, erc721metadata: false}))]480 pub flags: RpcCollectionFlags,481}482483impl<AccountId> From<CollectionVersion1<AccountId>> for RpcCollection<AccountId> {484 fn from(value: CollectionVersion1<AccountId>) -> Self {485 let CollectionVersion1 {486 name,487 description,488 owner,489 mode,490 access,491 token_prefix,492 mint_mode,493 sponsorship,494 limits,495 ..496 } = value;497498 RpcCollection {499 name: name.into_inner(),500 description: description.into_inner(),501 owner,502 mode,503 token_prefix: token_prefix.into_inner(),504 sponsorship,505 limits,506 permissions: CollectionPermissions {507 access: Some(access),508 mint_mode: Some(mint_mode),509 nesting: None,510 },511 token_property_permissions: Vec::default(),512 properties: Vec::default(),513 read_only: true,514515 flags: RpcCollectionFlags {516 foreign: false,517 erc721metadata: false,518 },519 }520 }521}522523pub struct RawEncoded(Vec<u8>);524525impl codec::Decode for RawEncoded {526 fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {527 let mut out = Vec::new();528 while let Ok(v) = input.read_byte() {529 out.push(v);530 }531 Ok(Self(out))532 }533}534535impl Deref for RawEncoded {536 type Target = Vec<u8>;537538 fn deref(&self) -> &Self::Target {539 return &self.0;540 }541}542543/// Data used for create collection.544///545/// All fields are wrapped in [`Option`], where `None` means chain default.546#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Derivative, MaxEncodedLen)]547#[derivative(Debug, Default(bound = ""))]548pub struct CreateCollectionData<AccountId> {549 /// Collection mode.550 #[derivative(Default(value = "CollectionMode::NFT"))]551 pub mode: CollectionMode,552553 /// Access mode.554 pub access: Option<AccessMode>,555556 /// Collection name.557 pub name: CollectionName,558559 /// Collection description.560 pub description: CollectionDescription,561562 /// Token prefix.563 pub token_prefix: CollectionTokenPrefix,564565 /// Pending collection sponsor.566 pub pending_sponsor: Option<AccountId>,567568 /// Collection limits.569 pub limits: Option<CollectionLimits>,570571 /// Collection permissions.572 pub permissions: Option<CollectionPermissions>,573574 /// Token property permissions.575 pub token_property_permissions: CollectionPropertiesPermissionsVec,576577 /// Collection properties.578 pub properties: CollectionPropertiesVec,579}580581/// Bounded vector of properties permissions. Max length is [`MAX_PROPERTIES_PER_ITEM`].582// TODO: maybe rename to PropertiesPermissionsVec583pub type CollectionPropertiesPermissionsVec =584 BoundedVec<PropertyKeyPermission, ConstU32<MAX_PROPERTIES_PER_ITEM>>;585586/// Bounded vector of properties. Max length is [`MAX_PROPERTIES_PER_ITEM`].587pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;588589/// Limits and restrictions of a collection.590///591/// All fields are wrapped in [`Option`], where `None` means chain default.592///593/// Update with `pallet_common::Pallet::clamp_limits`.594// IMPORTANT: When adding/removing fields from this struct - don't forget to also595#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]596#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]597// When adding/removing fields from this struct - don't forget to also update with `pallet_common::Pallet::clamp_limits`.598// TODO: move `pallet_common::Pallet::clamp_limits` into `impl CollectionLimits`.599// TODO: may be remove [`Option`] and **pub** from fields and create struct with default values.600pub struct CollectionLimits {601 /// How many tokens can a user have on one account.602 /// * Default - [`ACCOUNT_TOKEN_OWNERSHIP_LIMIT`].603 /// * Limit - [`MAX_TOKEN_OWNERSHIP`].604 pub account_token_ownership_limit: Option<u32>,605606 /// How many bytes of data are available for sponsorship.607 /// * Default - [`CUSTOM_DATA_LIMIT`].608 /// * Limit - [`CUSTOM_DATA_LIMIT`].609 pub sponsored_data_size: Option<u32>,610611 // FIXME should we delete this or repurpose it?612 /// Times in how many blocks we sponsor data.613 ///614 /// If is `Some(v)` then **setVariableMetadata** is sponsored if there is `v` block between transactions.615 ///616 /// * Default - [`SponsoringDisabled`](SponsoringRateLimit::SponsoringDisabled).617 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].618 ///619 /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]620 pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,621 /// Maximum amount of tokens inside the collection. Chain default: [`COLLECTION_TOKEN_LIMIT`]622623 /// How many tokens can be mined into this collection.624 ///625 /// * Default - [`COLLECTION_TOKEN_LIMIT`].626 /// * Limit - [`COLLECTION_TOKEN_LIMIT`].627 pub token_limit: Option<u32>,628629 /// Timeouts for transfer sponsoring.630 ///631 /// * Default632 /// - **Fungible** - [`FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]633 /// - **NFT** - [`NFT_SPONSOR_TRANSFER_TIMEOUT`]634 /// - **Refungible** - [`REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]635 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].636 pub sponsor_transfer_timeout: Option<u32>,637638 /// Timeout for sponsoring an approval in passed blocks.639 ///640 /// * Default - [`SPONSOR_APPROVE_TIMEOUT`].641 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].642 pub sponsor_approve_timeout: Option<u32>,643644 /// Whether the collection owner of the collection can send tokens (which belong to other users).645 ///646 /// * Default - **false**.647 pub owner_can_transfer: Option<bool>,648649 /// Can the collection owner burn other people's tokens.650 ///651 /// * Default - **true**.652 pub owner_can_destroy: Option<bool>,653654 /// Is it possible to send tokens from this collection between users.655 ///656 /// * Default - **true**.657 pub transfers_enabled: Option<bool>,658}659660impl CollectionLimits {661 pub fn with_default_limits(collection_type: CollectionMode) -> Self {662 CollectionLimits {663 account_token_ownership_limit: Some(ACCOUNT_TOKEN_OWNERSHIP_LIMIT),664 sponsored_data_size: Some(CUSTOM_DATA_LIMIT),665 sponsored_data_rate_limit: Some(SponsoringRateLimit::SponsoringDisabled),666 token_limit: Some(COLLECTION_TOKEN_LIMIT),667 sponsor_transfer_timeout: match collection_type {668 CollectionMode::NFT => Some(NFT_SPONSOR_TRANSFER_TIMEOUT),669 CollectionMode::ReFungible => Some(REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),670 CollectionMode::Fungible(_) => Some(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),671 },672 sponsor_approve_timeout: Some(SPONSOR_APPROVE_TIMEOUT),673 owner_can_transfer: Some(false),674 owner_can_destroy: Some(true),675 transfers_enabled: Some(true),676 }677 }678679 /// Get effective value for [`account_token_ownership_limit`](self.account_token_ownership_limit).680 pub fn account_token_ownership_limit(&self) -> u32 {681 self.account_token_ownership_limit682 .unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)683 .min(MAX_TOKEN_OWNERSHIP)684 }685686 /// Get effective value for [`sponsored_data_size`](self.sponsored_data_size).687 pub fn sponsored_data_size(&self) -> u32 {688 self.sponsored_data_size689 .unwrap_or(CUSTOM_DATA_LIMIT)690 .min(CUSTOM_DATA_LIMIT)691 }692693 /// Get effective value for [`token_limit`](self.token_limit).694 pub fn token_limit(&self) -> u32 {695 self.token_limit696 .unwrap_or(COLLECTION_TOKEN_LIMIT)697 .min(COLLECTION_TOKEN_LIMIT)698 }699700 // TODO: may be replace u32 to mode?701 /// Get effective value for [`sponsor_transfer_timeout`](self.sponsor_transfer_timeout).702 pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {703 self.sponsor_transfer_timeout704 .unwrap_or(default)705 .min(MAX_SPONSOR_TIMEOUT)706 }707708 /// Get effective value for [`sponsor_approve_timeout`](self.sponsor_approve_timeout).709 pub fn sponsor_approve_timeout(&self) -> u32 {710 self.sponsor_approve_timeout711 .unwrap_or(SPONSOR_APPROVE_TIMEOUT)712 .min(MAX_SPONSOR_TIMEOUT)713 }714715 /// Get effective value for [`owner_can_transfer`](self.owner_can_transfer).716 pub fn owner_can_transfer(&self) -> bool {717 self.owner_can_transfer.unwrap_or(false)718 }719720 /// Get effective value for [`owner_can_transfer_instaled`](self.owner_can_transfer_instaled).721 pub fn owner_can_transfer_instaled(&self) -> bool {722 self.owner_can_transfer.is_some()723 }724725 /// Get effective value for [`owner_can_destroy`](self.owner_can_destroy).726 pub fn owner_can_destroy(&self) -> bool {727 self.owner_can_destroy.unwrap_or(true)728 }729730 /// Get effective value for [`transfers_enabled`](self.transfers_enabled).731 pub fn transfers_enabled(&self) -> bool {732 self.transfers_enabled.unwrap_or(true)733 }734735 /// Get effective value for [`sponsored_data_rate_limit`](self.sponsored_data_rate_limit).736 pub fn sponsored_data_rate_limit(&self) -> Option<u32> {737 match self738 .sponsored_data_rate_limit739 .unwrap_or(SponsoringRateLimit::SponsoringDisabled)740 {741 SponsoringRateLimit::SponsoringDisabled => None,742 SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)),743 }744 }745}746747/// Permissions on certain operations within a collection.748///749/// Some fields are wrapped in [`Option`], where `None` means chain default.750///751/// Update with `pallet_common::Pallet::clamp_permissions`.752#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]753#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]754// When adding/removing fields from this struct - don't forget to also update `pallet_common::Pallet::clamp_permissions`.755// TODO: move `pallet_common::Pallet::clamp_permissions` into `impl CollectionPermissions`.756pub struct CollectionPermissions {757 /// Access mode.758 ///759 /// * Default - [`AccessMode::Normal`].760 pub access: Option<AccessMode>,761762 /// Minting allowance.763 ///764 /// * Default - **false**.765 pub mint_mode: Option<bool>,766767 /// Permissions for nesting.768 ///769 /// * Default770 /// - `token_owner` - **false**771 /// - `collection_admin` - **false**772 /// - `restricted` - **None**773 pub nesting: Option<NestingPermissions>,774}775776impl CollectionPermissions {777 /// Get effective value for [`access`](self.access).778 pub fn access(&self) -> AccessMode {779 self.access.unwrap_or(AccessMode::Normal)780 }781782 /// Get effective value for [`mint_mode`](self.mint_mode).783 pub fn mint_mode(&self) -> bool {784 self.mint_mode.unwrap_or(false)785 }786787 /// Get effective value for [`nesting`](self.nesting).788 pub fn nesting(&self) -> &NestingPermissions {789 static DEFAULT: NestingPermissions = NestingPermissions {790 token_owner: false,791 collection_admin: false,792 restricted: None,793 #[cfg(feature = "runtime-benchmarks")]794 permissive: false,795 };796 self.nesting.as_ref().unwrap_or(&DEFAULT)797 }798}799800/// Inner set for collections allowed to nest.801type OwnerRestrictedSetInner = BoundedBTreeSet<CollectionId, ConstU32<16>>;802803/// Wraper for collections set allowing nest.804#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]805#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]806#[derivative(Debug)]807pub struct OwnerRestrictedSet(808 #[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]809 #[derivative(Debug(format_with = "bounded::set_debug"))]810 pub OwnerRestrictedSetInner,811);812813impl OwnerRestrictedSet {814 /// Create new set.815 pub fn new() -> Self {816 Self(Default::default())817 }818}819impl core::ops::Deref for OwnerRestrictedSet {820 type Target = OwnerRestrictedSetInner;821 fn deref(&self) -> &Self::Target {822 &self.0823 }824}825impl core::ops::DerefMut for OwnerRestrictedSet {826 fn deref_mut(&mut self) -> &mut Self::Target {827 &mut self.0828 }829}830831/// Part of collection permissions, if set, defines who is able to nest tokens into other tokens.832#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]833#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]834#[derivative(Debug)]835pub struct NestingPermissions {836 /// Owner of token can nest tokens under it.837 pub token_owner: bool,838 /// Admin of token collection can nest tokens under token.839 pub collection_admin: bool,840 /// If set - only tokens from specified collections can be nested.841 pub restricted: Option<OwnerRestrictedSet>,842843 #[cfg(feature = "runtime-benchmarks")]844 /// Anyone can nest tokens, mutually exclusive with `token_owner`, `admin`.845 pub permissive: bool,846}847848/// Enum denominating how often can sponsoring occur if it is enabled.849///850/// Used for [`collection limits`](CollectionLimits).851#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]852#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]853pub enum SponsoringRateLimit {854 /// Sponsoring is disabled, and the collection sponsor will not pay for transactions855 SponsoringDisabled,856 /// Once per how many blocks can sponsorship of a transaction type occur857 Blocks(u32),858}859860/// Data used to describe an NFT at creation.861#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]862#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]863#[derivative(Debug)]864pub struct CreateNftData {865 /// Key-value pairs used to describe the token as metadata866 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]867 #[derivative(Debug(format_with = "bounded::vec_debug"))]868 /// Properties that wil be assignet to created item.869 pub properties: CollectionPropertiesVec,870}871872/// Data used to describe a Fungible token at creation.873#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]874#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]875pub struct CreateFungibleData {876 /// Number of fungible coins minted877 pub value: u128,878}879880/// Data used to describe a Refungible token at creation.881#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]882#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]883#[derivative(Debug)]884pub struct CreateReFungibleData {885 /// Number of pieces the RFT is split into886 pub pieces: u128,887888 /// Key-value pairs used to describe the token as metadata889 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]890 #[derivative(Debug(format_with = "bounded::vec_debug"))]891 pub properties: CollectionPropertiesVec,892}893894// TODO: remove this.895#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]896#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]897pub enum MetaUpdatePermission {898 ItemOwner,899 Admin,900 None,901}902903/// Enum holding data used for creation of all three item types.904/// Unified data for create item.905#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]906#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]907pub enum CreateItemData {908 /// Data for create NFT.909 NFT(CreateNftData),910 /// Data for create Fungible item.911 Fungible(CreateFungibleData),912 /// Data for create ReFungible item.913 ReFungible(CreateReFungibleData),914}915916/// Extended data for create NFT.917#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]918#[derivative(Debug)]919pub struct CreateNftExData<CrossAccountId> {920 /// Properties that wil be assignet to created item.921 #[derivative(Debug(format_with = "bounded::vec_debug"))]922 pub properties: CollectionPropertiesVec,923924 /// Owner of creating item.925 pub owner: CrossAccountId,926}927928/// Extended data for create ReFungible item.929#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]930#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]931pub struct CreateRefungibleExMultipleOwners<CrossAccountId> {932 #[derivative(Debug(format_with = "bounded::map_debug"))]933 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,934 #[derivative(Debug(format_with = "bounded::vec_debug"))]935 pub properties: CollectionPropertiesVec,936}937938/// Extended data for create ReFungible item.939#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]940#[derivative(Debug(bound = "CrossAccountId: fmt::Debug"))]941pub struct CreateRefungibleExSingleOwner<CrossAccountId> {942 pub user: CrossAccountId,943 pub pieces: u128,944 #[derivative(Debug(format_with = "bounded::vec_debug"))]945 pub properties: CollectionPropertiesVec,946}947948/// Unified extended data for creating item.949#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]950#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]951pub enum CreateItemExData<CrossAccountId> {952 /// Extended data for create NFT.953 NFT(954 #[derivative(Debug(format_with = "bounded::vec_debug"))]955 BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,956 ),957958 /// Extended data for create Fungible item.959 Fungible(960 #[derivative(Debug(format_with = "bounded::map_debug"))]961 BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,962 ),963964 /// Extended data for create ReFungible item in case of965 /// many tokens, each may have only one owner966 RefungibleMultipleItems(967 #[derivative(Debug(format_with = "bounded::vec_debug"))]968 BoundedVec<CreateRefungibleExSingleOwner<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,969 ),970971 /// Extended data for create ReFungible item in case of972 /// single token, which may have many owners973 RefungibleMultipleOwners(CreateRefungibleExMultipleOwners<CrossAccountId>),974}975976impl From<CreateNftData> for CreateItemData {977 fn from(item: CreateNftData) -> Self {978 CreateItemData::NFT(item)979 }980}981982impl From<CreateReFungibleData> for CreateItemData {983 fn from(item: CreateReFungibleData) -> Self {984 CreateItemData::ReFungible(item)985 }986}987988impl From<CreateFungibleData> for CreateItemData {989 fn from(item: CreateFungibleData) -> Self {990 CreateItemData::Fungible(item)991 }992}993994/// Token's address, dictated by its collection and token IDs.995#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]996#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]997// todo possibly rename to be used generally as an address pair998pub struct TokenChild {999 /// Token id.1000 pub token: TokenId,10011002 /// Collection id.1003 pub collection: CollectionId,1004}10051006/// Collection statistics.1007#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]1008#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1009pub struct CollectionStats {1010 /// Number of created items.1011 pub created: u32,10121013 /// Number of burned items.1014 pub destroyed: u32,10151016 /// Number of current items.1017 pub alive: u32,1018}10191020/// This type works like [`PhantomData`] but supports generating _scale-info_ descriptions to generate node metadata.1021#[derive(Encode, Decode, Clone, Debug)]1022#[cfg_attr(feature = "std", derive(PartialEq))]1023pub struct PhantomType<T>(core::marker::PhantomData<T>);10241025impl<T: TypeInfo + 'static> TypeInfo for PhantomType<T> {1026 type Identity = PhantomType<T>;10271028 fn type_info() -> scale_info::Type {1029 use scale_info::{1030 Type, Path,1031 build::{FieldsBuilder, UnnamedFields},1032 form::MetaForm,1033 type_params,1034 };1035 Type::builder()1036 .path(Path::new("up_data_structs", "PhantomType"))1037 .type_params(type_params!(T))1038 .composite(1039 <FieldsBuilder<MetaForm, UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()),1040 )1041 }1042}1043impl<T> MaxEncodedLen for PhantomType<T> {1044 fn max_encoded_len() -> usize {1045 01046 }1047}10481049/// Bounded vector of bytes.1050pub type BoundedBytes<S> = BoundedVec<u8, S>;10511052/// Extra properties for external collections.1053pub type AuxPropertyValue = BoundedBytes<ConstU32<MAX_AUX_PROPERTY_VALUE_LENGTH>>;10541055/// Property key.1056pub type PropertyKey = BoundedBytes<ConstU32<MAX_PROPERTY_KEY_LENGTH>>;10571058/// Property value.1059pub type PropertyValue = BoundedBytes<ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;10601061/// Property permission.1062#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone, Default)]1063#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1064pub struct PropertyPermission {1065 /// Permission to change the property and property permission.1066 ///1067 /// If it **false** then you can not change corresponding property even if [`collection_admin`] and [`token_owner`] are **true**.1068 pub mutable: bool,10691070 /// Change permission for the collection administrator.1071 pub collection_admin: bool,10721073 /// Permission to change the property for the owner of the token.1074 pub token_owner: bool,1075}10761077impl PropertyPermission {1078 /// Creates mutable property permission but changes restricted for collection admin and token owner.1079 pub fn none() -> Self {1080 Self {1081 mutable: true,1082 collection_admin: false,1083 token_owner: false,1084 }1085 }1086}10871088/// Property is simpl key-value record.1089#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, MaxEncodedLen)]1090#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1091pub struct Property {1092 /// Property key.1093 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1094 pub key: PropertyKey,10951096 /// Property value.1097 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1098 pub value: PropertyValue,1099}11001101impl Into<(PropertyKey, PropertyValue)> for Property {1102 fn into(self) -> (PropertyKey, PropertyValue) {1103 (self.key, self.value)1104 }1105}11061107/// Record for proprty key permission.1108#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]1109#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1110pub struct PropertyKeyPermission {1111 /// Key.1112 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1113 pub key: PropertyKey,11141115 /// Permission.1116 pub permission: PropertyPermission,1117}11181119impl Into<(PropertyKey, PropertyPermission)> for PropertyKeyPermission {1120 fn into(self) -> (PropertyKey, PropertyPermission) {1121 (self.key, self.permission)1122 }1123}11241125/// Errors for properties actions.1126#[derive(Debug)]1127pub enum PropertiesError {1128 /// The space allocated for properties has run out.1129 ///1130 /// * Limit for colection - [`MAX_COLLECTION_PROPERTIES_SIZE`].1131 /// * Limit for token - [`MAX_TOKEN_PROPERTIES_SIZE`].1132 NoSpaceForProperty,11331134 /// The property limit has been reached.1135 ///1136 /// * Limit - [`MAX_PROPERTIES_PER_ITEM`].1137 PropertyLimitReached,11381139 /// Property key contains not allowed character.1140 InvalidCharacterInPropertyKey,11411142 /// Property key length is too long.1143 ///1144 /// * Limit - [`MAX_PROPERTY_KEY_LENGTH`].1145 PropertyKeyIsTooLong,11461147 /// Property key is empty.1148 EmptyPropertyKey,1149}11501151/// Token owner error: it could be either `NotFound` ot `MultipleOwners`.1152#[derive(Debug)]1153pub enum TokenOwnerError {1154 NotFound,1155 MultipleOwners,1156}11571158/// Marker for scope of property.1159///1160/// Scoped property can't be changed by user. Used for external collections.1161#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Clone, Copy)]1162pub enum PropertyScope {1163 None,1164 Rmrk,1165}11661167impl PropertyScope {1168 pub fn prefix(&self) -> &'static [u8] {1169 match self {1170 Self::None => b"",1171 Self::Rmrk => b"rmrk:",1172 }1173 }1174 /// Apply scope to property key.1175 pub fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {1176 let prefix = self.prefix();1177 if prefix == b"" {1178 return Ok(key);1179 }1180 [prefix, key.as_slice()]1181 .concat()1182 .try_into()1183 .map_err(|_| PropertiesError::PropertyKeyIsTooLong)1184 }1185}11861187/// Trait for operate with properties.1188pub trait TrySetProperty: Sized {1189 type Value;11901191 /// Try to set property with scope.1192 fn try_scoped_set(1193 &mut self,1194 scope: PropertyScope,1195 key: PropertyKey,1196 value: Self::Value,1197 ) -> Result<Option<Self::Value>, PropertiesError>;11981199 /// Try to set property with scope from iterator.1200 fn try_scoped_set_from_iter<I, KV>(1201 &mut self,1202 scope: PropertyScope,1203 iter: I,1204 ) -> Result<(), PropertiesError>1205 where1206 I: Iterator<Item = KV>,1207 KV: Into<(PropertyKey, Self::Value)>,1208 {1209 for kv in iter {1210 let (key, value) = kv.into();1211 self.try_scoped_set(scope, key, value)?;1212 }12131214 Ok(())1215 }12161217 /// Try to set property.1218 fn try_set(1219 &mut self,1220 key: PropertyKey,1221 value: Self::Value,1222 ) -> Result<Option<Self::Value>, PropertiesError> {1223 self.try_scoped_set(PropertyScope::None, key, value)1224 }12251226 /// Try to set property from iterator.1227 fn try_set_from_iter<I, KV>(&mut self, iter: I) -> Result<(), PropertiesError>1228 where1229 I: Iterator<Item = KV>,1230 KV: Into<(PropertyKey, Self::Value)>,1231 {1232 self.try_scoped_set_from_iter(PropertyScope::None, iter)1233 }1234}12351236/// Wrapped map for storing properties.1237#[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]1238#[derivative(Default(bound = ""))]1239pub struct PropertiesMap<Value>(1240 BoundedBTreeMap<PropertyKey, Value, ConstU32<MAX_PROPERTIES_PER_ITEM>>,1241);12421243impl<Value> PropertiesMap<Value> {1244 /// Create new property map.1245 pub fn new() -> Self {1246 Self(BoundedBTreeMap::new())1247 }12481249 /// Remove property from map.1250 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<Value>, PropertiesError> {1251 Self::check_property_key(key)?;12521253 Ok(self.0.remove(key))1254 }12551256 /// Get property with appropriate key from map.1257 pub fn get(&self, key: &PropertyKey) -> Option<&Value> {1258 self.0.get(key)1259 }12601261 /// Check if map contains key.1262 pub fn contains_key(&self, key: &PropertyKey) -> bool {1263 self.0.contains_key(key)1264 }12651266 /// Check if map contains key with key validation.1267 fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {1268 if key.is_empty() {1269 return Err(PropertiesError::EmptyPropertyKey);1270 }12711272 for byte in key.as_slice().iter() {1273 let byte = *byte;12741275 if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' && byte != b'.' {1276 return Err(PropertiesError::InvalidCharacterInPropertyKey);1277 }1278 }12791280 Ok(())1281 }12821283 pub fn values(&self) -> impl Iterator<Item = &Value> {1284 self.0.values()1285 }12861287 pub fn iter(&self) -> impl Iterator<Item = (&PropertyKey, &Value)> {1288 self.0.iter()1289 }1290}12911292impl<Value> IntoIterator for PropertiesMap<Value> {1293 type Item = (PropertyKey, Value);1294 type IntoIter = <1295 BoundedBTreeMap<1296 PropertyKey,1297 Value,1298 ConstU32<MAX_PROPERTIES_PER_ITEM>1299 > as IntoIterator1300 >::IntoIter;13011302 fn into_iter(self) -> Self::IntoIter {1303 self.0.into_iter()1304 }1305}13061307impl<Value> TrySetProperty for PropertiesMap<Value> {1308 type Value = Value;13091310 fn try_scoped_set(1311 &mut self,1312 scope: PropertyScope,1313 key: PropertyKey,1314 value: Self::Value,1315 ) -> Result<Option<Self::Value>, PropertiesError> {1316 Self::check_property_key(&key)?;13171318 let key = scope.apply(key)?;1319 self.01320 .try_insert(key, value)1321 .map_err(|_| PropertiesError::PropertyLimitReached)1322 }1323}13241325/// Alias for property permissions map.1326pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;13271328fn slice_size(data: &[u8]) -> u32 {1329 scoped_slice_size(PropertyScope::None, data)1330}1331fn scoped_slice_size(scope: PropertyScope, data: &[u8]) -> u32 {1332 use codec::Compact;1333 let prefix = scope.prefix();1334 <Compact<u32>>::encoded_size(&Compact(data.len() as u32 + prefix.len() as u32)) as u321335 + data.len() as u321336 + prefix.len() as u321337}13381339/// Wrapper for properties map with consumed space control.1340#[derive(Encode, Decode, TypeInfo, Clone, PartialEq)]1341pub struct Properties<const S: u32> {1342 map: PropertiesMap<PropertyValue>,1343 consumed_space: u32,1344 // May be not zero, previously served as a current S generic1345 _reserved: u32,1346}13471348impl<const S: u32> MaxEncodedLen for Properties<S> {1349 fn max_encoded_len() -> usize {1350 // len of map + len of consumed_space + len of space_limit1351 u32::max_encoded_len() * 3 + S as usize1352 }1353}13541355impl<const S: u32> Default for Properties<S> {1356 fn default() -> Self {1357 Self::new()1358 }1359}13601361impl<const S: u32> Properties<S> {1362 /// Create new properies container.1363 pub fn new() -> Self {1364 Self {1365 map: PropertiesMap::new(),1366 consumed_space: 0,1367 _reserved: 0,1368 }1369 }13701371 /// Remove propery with appropiate key.1372 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<PropertyValue>, PropertiesError> {1373 let value = self.map.remove(key)?;13741375 if let Some(ref value) = value {1376 let kv_len = slice_size(key) + slice_size(value);1377 self.consumed_space = self.consumed_space.saturating_sub(kv_len);1378 }13791380 Ok(value)1381 }13821383 /// Get property with appropriate key.1384 pub fn get(&self, key: &PropertyKey) -> Option<&PropertyValue> {1385 self.map.get(key)1386 }13871388 /// Recomputes the consumed space for the current properties state.1389 /// Needed to repair a token due to a bug fixed in the [PR #733](https://github.com/UniqueNetwork/unique-chain/pull/773).1390 pub fn recompute_consumed_space(&mut self) {1391 self.consumed_space = self1392 .map1393 .iter()1394 .map(|(key, value)| slice_size(key) + slice_size(value))1395 .sum();1396 }1397}13981399impl<const S: u32> IntoIterator for Properties<S> {1400 type Item = (PropertyKey, PropertyValue);1401 type IntoIter = <PropertiesMap<PropertyValue> as IntoIterator>::IntoIter;14021403 fn into_iter(self) -> Self::IntoIter {1404 self.map.into_iter()1405 }1406}14071408impl<const S: u32> TrySetProperty for Properties<S> {1409 type Value = PropertyValue;14101411 fn try_scoped_set(1412 &mut self,1413 scope: PropertyScope,1414 key: PropertyKey,1415 value: Self::Value,1416 ) -> Result<Option<Self::Value>, PropertiesError> {1417 let key_size = scoped_slice_size(scope, &key);1418 let value_size = slice_size(&value) as u32;14191420 if self.consumed_space + value_size + key_size > S && !cfg!(feature = "runtime-benchmarks")1421 {1422 return Err(PropertiesError::NoSpaceForProperty);1423 }14241425 let old_value = self.map.try_scoped_set(scope, key, value)?;14261427 if let Some(old_value) = old_value.as_ref() {1428 let old_value_size = slice_size(&old_value);1429 self.consumed_space = self.consumed_space.saturating_sub(old_value_size) + value_size;1430 } else {1431 self.consumed_space += key_size + value_size;1432 }14331434 Ok(old_value)1435 }1436}14371438pub type CollectionProperties = Properties<MAX_COLLECTION_PROPERTIES_SIZE>;1439pub type TokenProperties = Properties<MAX_TOKEN_PROPERTIES_SIZE>;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//! # Primitives crate.18//!19//! This crate contains types, traits and constants.2021#![cfg_attr(not(feature = "std"), no_std)]2223use core::{24 convert::{TryFrom, TryInto},25 fmt,26 ops::Deref,27};28use frame_support::storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet};2930#[cfg(feature = "serde")]31use serde::{Serialize, Deserialize};3233use sp_core::U256;34use sp_runtime::{ArithmeticError, sp_std::prelude::Vec};35use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};36use bondrewd::Bitfields;37use frame_support::{BoundedVec, traits::ConstU32};38use derivative::Derivative;39use scale_info::TypeInfo;4041mod bondrewd_codec;42mod bounded;43pub mod budget;44pub mod mapping;45mod migration;4647/// Maximum of decimal points.48pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;4950/// Maximum pieces for refungible token.51pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;52pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;5354/// Maximum tokens for user.55pub const MAX_TOKEN_OWNERSHIP: u32 = if cfg!(not(feature = "limit-testing")) {56 100_00057} else {58 1059};6061/// Maximum for collections can be created.62pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {63 100_00064} else {65 1066};6768/// Maximum for various custom data of token.69pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {70 204871} else {72 1073};7475/// Maximum admins per collection.76pub const COLLECTION_ADMINS_LIMIT: u32 = 5;7778/// Maximum tokens per collection.79pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;8081/// Maximum tokens per account.82pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {83 1_000_00084} else {85 1086};8788/// Default timeout for transfer sponsoring NFT item.89pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;90/// Default timeout for transfer sponsoring fungible item.91pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;92/// Default timeout for transfer sponsoring refungible item.93pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;9495/// Default timeout for sponsored approving.96pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;9798// Schema limits99pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;100pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;101pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;102103// TODO: not used. Delete?104pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;105106/// Maximal length of a collection name.107pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;108109/// Maximal length of a collection description.110pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;111112/// Maximal length of a token prefix.113pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16;114115/// Maximal length of a property key.116pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256;117118/// Maximal length of a property value.119pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768;120121/// A maximum number of token properties.122pub const MAX_PROPERTIES_PER_ITEM: u32 = 64;123124/// Maximal lenght of extended property value.125pub const MAX_AUX_PROPERTY_VALUE_LENGTH: u32 = 2048;126127/// Maximum size for all collection properties.128pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960;129130/// Maximum size of all token properties.131pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768;132133/// How much items can be created per single134/// create_many call.135pub const MAX_ITEMS_PER_BATCH: u32 = 200;136137/// Used for limit bounded types of token custom data.138pub type CustomDataLimit = ConstU32<CUSTOM_DATA_LIMIT>;139140/// Collection id.141#[derive(142 Encode,143 Decode,144 PartialEq,145 Eq,146 PartialOrd,147 Ord,148 Clone,149 Copy,150 Debug,151 Default,152 TypeInfo,153 MaxEncodedLen,154)]155#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]156pub struct CollectionId(pub u32);157impl EncodeLike<u32> for CollectionId {}158impl EncodeLike<CollectionId> for u32 {}159160impl From<u32> for CollectionId {161 fn from(value: u32) -> Self {162 Self(value)163 }164}165166/// Token id.167#[derive(168 Encode,169 Decode,170 PartialEq,171 Eq,172 PartialOrd,173 Ord,174 Clone,175 Copy,176 Debug,177 Default,178 TypeInfo,179 MaxEncodedLen,180)]181#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]182pub struct TokenId(pub u32);183impl EncodeLike<u32> for TokenId {}184impl EncodeLike<TokenId> for u32 {}185186impl TokenId {187 /// Try to get next token id.188 ///189 /// If next id cause overflow, then [`ArithmeticError::Overflow`] returned.190 pub fn try_next(self) -> Result<TokenId, ArithmeticError> {191 self.0192 .checked_add(1)193 .ok_or(ArithmeticError::Overflow)194 .map(Self)195 }196}197198impl From<TokenId> for U256 {199 fn from(t: TokenId) -> Self {200 t.0.into()201 }202}203204impl TryFrom<U256> for TokenId {205 type Error = &'static str;206207 fn try_from(value: U256) -> Result<Self, Self::Error> {208 Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))209 }210}211212/// Token data.213#[struct_versioning::versioned(version = 2, upper)]214#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]215#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]216pub struct TokenData<CrossAccountId> {217 /// Properties of token.218 pub properties: Vec<Property>,219220 /// Token owner.221 pub owner: Option<CrossAccountId>,222223 /// Token pieces.224 #[version(2.., upper(0))]225 pub pieces: u128,226}227228// TODO: unused type229pub struct OverflowError;230impl From<OverflowError> for &'static str {231 fn from(_: OverflowError) -> Self {232 "overflow occured"233 }234}235236/// Alias for decimal points type.237pub type DecimalPoints = u8;238239/// Collection mode.240///241/// Collection can represent various types of tokens.242/// Each collection can contain only one type of tokens at a time.243/// This type helps to understand which tokens the collection contains.244#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]245#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]246pub enum CollectionMode {247 /// Non fungible tokens.248 NFT,249 /// Fungible tokens.250 Fungible(DecimalPoints),251 /// Refungible tokens.252 ReFungible,253}254255impl CollectionMode {256 /// Get collection mod as number.257 pub fn id(&self) -> u8 {258 match self {259 CollectionMode::NFT => 1,260 CollectionMode::Fungible(_) => 2,261 CollectionMode::ReFungible => 3,262 }263 }264}265266// TODO: unused trait267pub trait SponsoringResolve<AccountId, Call> {268 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;269}270271/// Access mode for some token operations.272#[derive(Encode, Decode, Eq, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]273#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]274pub enum AccessMode {275 /// Access grant for owner and admins. Used as default.276 Normal,277 /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.278 AllowList,279}280impl Default for AccessMode {281 fn default() -> Self {282 Self::Normal283 }284}285286// TODO: remove in future.287#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]288#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]289pub enum SchemaVersion {290 ImageURL,291 Unique,292}293impl Default for SchemaVersion {294 fn default() -> Self {295 Self::ImageURL296 }297}298299// TODO: unused type300#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]301#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]302pub struct Ownership<AccountId> {303 pub owner: AccountId,304 pub fraction: u128,305}306307/// The state of collection sponsorship.308#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]309#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]310pub enum SponsorshipState<AccountId> {311 /// The fees are applied to the transaction sender.312 Disabled,313 /// The sponsor is under consideration. Until the sponsor gives his consent,314 /// the fee will still be charged to sender.315 Unconfirmed(AccountId),316 /// Transactions are sponsored by specified account.317 Confirmed(AccountId),318}319320impl<AccountId> SponsorshipState<AccountId> {321 /// Get a sponsor of the collection who has confirmed his status.322 pub fn sponsor(&self) -> Option<&AccountId> {323 match self {324 Self::Confirmed(sponsor) => Some(sponsor),325 _ => None,326 }327 }328329 /// Get a sponsor of the collection who has pending or confirmed status.330 pub fn pending_sponsor(&self) -> Option<&AccountId> {331 match self {332 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),333 _ => None,334 }335 }336337 /// Whether the sponsorship is confirmed.338 pub fn confirmed(&self) -> bool {339 matches!(self, Self::Confirmed(_))340 }341}342343impl<T> Default for SponsorshipState<T> {344 fn default() -> Self {345 Self::Disabled346 }347}348349pub type CollectionName = BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>;350pub type CollectionDescription = BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>;351pub type CollectionTokenPrefix = BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>;352353#[derive(Bitfields, Clone, Copy, PartialEq, Eq, Debug, Default)]354#[bondrewd(enforce_bytes = 1)]355pub struct CollectionFlags {356 /// Tokens in foreign collections can be transferred, but not burnt357 #[bondrewd(bits = "0..1")]358 pub foreign: bool,359 /// Supports ERC721Metadata360 #[bondrewd(bits = "1..2")]361 pub erc721metadata: bool,362 /// External collections can't be managed using `unique` api363 #[bondrewd(bits = "7..8")]364 pub external: bool,365366 #[bondrewd(reserve, bits = "2..7")]367 pub reserved: u8,368}369bondrewd_codec!(CollectionFlags);370371/// Base structure for represent collection.372///373/// Used to provide basic functionality for all types of collections.374///375/// #### Note376/// Collection parameters, used in storage (see [`RpcCollection`] for the RPC version).377#[struct_versioning::versioned(version = 2, upper)]378#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]379pub struct Collection<AccountId> {380 /// Collection owner account.381 pub owner: AccountId,382383 /// Collection mode.384 pub mode: CollectionMode,385386 /// Access mode.387 #[version(..2)]388 pub access: AccessMode,389390 /// Collection name.391 pub name: CollectionName,392393 /// Collection description.394 pub description: CollectionDescription,395396 /// Token prefix.397 pub token_prefix: CollectionTokenPrefix,398399 #[version(..2)]400 pub mint_mode: bool,401402 #[version(..2)]403 pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,404405 #[version(..2)]406 pub schema_version: SchemaVersion,407408 /// The state of sponsorship of the collection.409 pub sponsorship: SponsorshipState<AccountId>,410411 /// Collection limits.412 pub limits: CollectionLimits,413414 /// Collection permissions.415 #[version(2.., upper(Default::default()))]416 pub permissions: CollectionPermissions,417418 #[version(2.., upper(Default::default()))]419 pub flags: CollectionFlags,420421 #[version(..2)]422 pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,423424 #[version(..2)]425 pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,426427 #[version(..2)]428 pub meta_update_permission: MetaUpdatePermission,429}430431#[derive(Debug, Encode, Decode, Clone, PartialEq, TypeInfo)]432#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]433pub struct RpcCollectionFlags {434 /// Is collection is foreign.435 pub foreign: bool,436 /// Collection supports ERC721Metadata.437 pub erc721metadata: bool,438}439440/// Collection parameters, used in RPC calls (see [`Collection`] for the storage version).441#[struct_versioning::versioned(version = 2, upper)]442#[derive(Debug, Encode, Decode, Clone, PartialEq, TypeInfo)]443#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]444pub struct RpcCollection<AccountId> {445 /// Collection owner account.446 pub owner: AccountId,447448 /// Collection mode.449 pub mode: CollectionMode,450451 /// Collection name.452 pub name: Vec<u16>,453454 /// Collection description.455 pub description: Vec<u16>,456457 /// Token prefix.458 pub token_prefix: Vec<u8>,459460 /// The state of sponsorship of the collection.461 pub sponsorship: SponsorshipState<AccountId>,462463 /// Collection limits.464 pub limits: CollectionLimits,465466 /// Collection permissions.467 pub permissions: CollectionPermissions,468469 /// Token property permissions.470 pub token_property_permissions: Vec<PropertyKeyPermission>,471472 /// Collection properties.473 pub properties: Vec<Property>,474475 /// Is collection read only.476 pub read_only: bool,477478 /// Extra collection flags479 #[version(2.., upper(RpcCollectionFlags {foreign: false, erc721metadata: false}))]480 pub flags: RpcCollectionFlags,481}482483impl<AccountId> From<CollectionVersion1<AccountId>> for RpcCollection<AccountId> {484 fn from(value: CollectionVersion1<AccountId>) -> Self {485 let CollectionVersion1 {486 name,487 description,488 owner,489 mode,490 access,491 token_prefix,492 mint_mode,493 sponsorship,494 limits,495 ..496 } = value;497498 RpcCollection {499 name: name.into_inner(),500 description: description.into_inner(),501 owner,502 mode,503 token_prefix: token_prefix.into_inner(),504 sponsorship,505 limits,506 permissions: CollectionPermissions {507 access: Some(access),508 mint_mode: Some(mint_mode),509 nesting: None,510 },511 token_property_permissions: Vec::default(),512 properties: Vec::default(),513 read_only: true,514515 flags: RpcCollectionFlags {516 foreign: false,517 erc721metadata: false,518 },519 }520 }521}522523pub struct RawEncoded(Vec<u8>);524525impl codec::Decode for RawEncoded {526 fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {527 let mut out = Vec::new();528 while let Ok(v) = input.read_byte() {529 out.push(v);530 }531 Ok(Self(out))532 }533}534535impl Deref for RawEncoded {536 type Target = Vec<u8>;537538 fn deref(&self) -> &Self::Target {539 &self.0540 }541}542543/// Data used for create collection.544///545/// All fields are wrapped in [`Option`], where `None` means chain default.546#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Derivative, MaxEncodedLen)]547#[derivative(Debug, Default(bound = ""))]548pub struct CreateCollectionData<AccountId> {549 /// Collection mode.550 #[derivative(Default(value = "CollectionMode::NFT"))]551 pub mode: CollectionMode,552553 /// Access mode.554 pub access: Option<AccessMode>,555556 /// Collection name.557 pub name: CollectionName,558559 /// Collection description.560 pub description: CollectionDescription,561562 /// Token prefix.563 pub token_prefix: CollectionTokenPrefix,564565 /// Pending collection sponsor.566 pub pending_sponsor: Option<AccountId>,567568 /// Collection limits.569 pub limits: Option<CollectionLimits>,570571 /// Collection permissions.572 pub permissions: Option<CollectionPermissions>,573574 /// Token property permissions.575 pub token_property_permissions: CollectionPropertiesPermissionsVec,576577 /// Collection properties.578 pub properties: CollectionPropertiesVec,579}580581/// Bounded vector of properties permissions. Max length is [`MAX_PROPERTIES_PER_ITEM`].582// TODO: maybe rename to PropertiesPermissionsVec583pub type CollectionPropertiesPermissionsVec =584 BoundedVec<PropertyKeyPermission, ConstU32<MAX_PROPERTIES_PER_ITEM>>;585586/// Bounded vector of properties. Max length is [`MAX_PROPERTIES_PER_ITEM`].587pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;588589/// Limits and restrictions of a collection.590///591/// All fields are wrapped in [`Option`], where `None` means chain default.592///593/// Update with `pallet_common::Pallet::clamp_limits`.594// IMPORTANT: When adding/removing fields from this struct - don't forget to also595#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]596#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]597// When adding/removing fields from this struct - don't forget to also update with `pallet_common::Pallet::clamp_limits`.598// TODO: move `pallet_common::Pallet::clamp_limits` into `impl CollectionLimits`.599// TODO: may be remove [`Option`] and **pub** from fields and create struct with default values.600pub struct CollectionLimits {601 /// How many tokens can a user have on one account.602 /// * Default - [`ACCOUNT_TOKEN_OWNERSHIP_LIMIT`].603 /// * Limit - [`MAX_TOKEN_OWNERSHIP`].604 pub account_token_ownership_limit: Option<u32>,605606 /// How many bytes of data are available for sponsorship.607 /// * Default - [`CUSTOM_DATA_LIMIT`].608 /// * Limit - [`CUSTOM_DATA_LIMIT`].609 pub sponsored_data_size: Option<u32>,610611 // FIXME should we delete this or repurpose it?612 /// Times in how many blocks we sponsor data.613 ///614 /// If is `Some(v)` then **setVariableMetadata** is sponsored if there is `v` block between transactions.615 ///616 /// * Default - [`SponsoringDisabled`](SponsoringRateLimit::SponsoringDisabled).617 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].618 ///619 /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]620 pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,621 /// Maximum amount of tokens inside the collection. Chain default: [`COLLECTION_TOKEN_LIMIT`]622623 /// How many tokens can be mined into this collection.624 ///625 /// * Default - [`COLLECTION_TOKEN_LIMIT`].626 /// * Limit - [`COLLECTION_TOKEN_LIMIT`].627 pub token_limit: Option<u32>,628629 /// Timeouts for transfer sponsoring.630 ///631 /// * Default632 /// - **Fungible** - [`FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]633 /// - **NFT** - [`NFT_SPONSOR_TRANSFER_TIMEOUT`]634 /// - **Refungible** - [`REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]635 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].636 pub sponsor_transfer_timeout: Option<u32>,637638 /// Timeout for sponsoring an approval in passed blocks.639 ///640 /// * Default - [`SPONSOR_APPROVE_TIMEOUT`].641 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].642 pub sponsor_approve_timeout: Option<u32>,643644 /// Whether the collection owner of the collection can send tokens (which belong to other users).645 ///646 /// * Default - **false**.647 pub owner_can_transfer: Option<bool>,648649 /// Can the collection owner burn other people's tokens.650 ///651 /// * Default - **true**.652 pub owner_can_destroy: Option<bool>,653654 /// Is it possible to send tokens from this collection between users.655 ///656 /// * Default - **true**.657 pub transfers_enabled: Option<bool>,658}659660impl CollectionLimits {661 pub fn with_default_limits(collection_type: CollectionMode) -> Self {662 CollectionLimits {663 account_token_ownership_limit: Some(ACCOUNT_TOKEN_OWNERSHIP_LIMIT),664 sponsored_data_size: Some(CUSTOM_DATA_LIMIT),665 sponsored_data_rate_limit: Some(SponsoringRateLimit::SponsoringDisabled),666 token_limit: Some(COLLECTION_TOKEN_LIMIT),667 sponsor_transfer_timeout: match collection_type {668 CollectionMode::NFT => Some(NFT_SPONSOR_TRANSFER_TIMEOUT),669 CollectionMode::ReFungible => Some(REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),670 CollectionMode::Fungible(_) => Some(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),671 },672 sponsor_approve_timeout: Some(SPONSOR_APPROVE_TIMEOUT),673 owner_can_transfer: Some(false),674 owner_can_destroy: Some(true),675 transfers_enabled: Some(true),676 }677 }678679 /// Get effective value for [`account_token_ownership_limit`](self.account_token_ownership_limit).680 pub fn account_token_ownership_limit(&self) -> u32 {681 self.account_token_ownership_limit682 .unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)683 .min(MAX_TOKEN_OWNERSHIP)684 }685686 /// Get effective value for [`sponsored_data_size`](self.sponsored_data_size).687 pub fn sponsored_data_size(&self) -> u32 {688 self.sponsored_data_size689 .unwrap_or(CUSTOM_DATA_LIMIT)690 .min(CUSTOM_DATA_LIMIT)691 }692693 /// Get effective value for [`token_limit`](self.token_limit).694 pub fn token_limit(&self) -> u32 {695 self.token_limit696 .unwrap_or(COLLECTION_TOKEN_LIMIT)697 .min(COLLECTION_TOKEN_LIMIT)698 }699700 // TODO: may be replace u32 to mode?701 /// Get effective value for [`sponsor_transfer_timeout`](self.sponsor_transfer_timeout).702 pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {703 self.sponsor_transfer_timeout704 .unwrap_or(default)705 .min(MAX_SPONSOR_TIMEOUT)706 }707708 /// Get effective value for [`sponsor_approve_timeout`](self.sponsor_approve_timeout).709 pub fn sponsor_approve_timeout(&self) -> u32 {710 self.sponsor_approve_timeout711 .unwrap_or(SPONSOR_APPROVE_TIMEOUT)712 .min(MAX_SPONSOR_TIMEOUT)713 }714715 /// Get effective value for [`owner_can_transfer`](self.owner_can_transfer).716 pub fn owner_can_transfer(&self) -> bool {717 self.owner_can_transfer.unwrap_or(false)718 }719720 /// Get effective value for [`owner_can_transfer_instaled`](self.owner_can_transfer_instaled).721 pub fn owner_can_transfer_instaled(&self) -> bool {722 self.owner_can_transfer.is_some()723 }724725 /// Get effective value for [`owner_can_destroy`](self.owner_can_destroy).726 pub fn owner_can_destroy(&self) -> bool {727 self.owner_can_destroy.unwrap_or(true)728 }729730 /// Get effective value for [`transfers_enabled`](self.transfers_enabled).731 pub fn transfers_enabled(&self) -> bool {732 self.transfers_enabled.unwrap_or(true)733 }734735 /// Get effective value for [`sponsored_data_rate_limit`](self.sponsored_data_rate_limit).736 pub fn sponsored_data_rate_limit(&self) -> Option<u32> {737 match self738 .sponsored_data_rate_limit739 .unwrap_or(SponsoringRateLimit::SponsoringDisabled)740 {741 SponsoringRateLimit::SponsoringDisabled => None,742 SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)),743 }744 }745}746747/// Permissions on certain operations within a collection.748///749/// Some fields are wrapped in [`Option`], where `None` means chain default.750///751/// Update with `pallet_common::Pallet::clamp_permissions`.752#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]753#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]754// When adding/removing fields from this struct - don't forget to also update `pallet_common::Pallet::clamp_permissions`.755// TODO: move `pallet_common::Pallet::clamp_permissions` into `impl CollectionPermissions`.756pub struct CollectionPermissions {757 /// Access mode.758 ///759 /// * Default - [`AccessMode::Normal`].760 pub access: Option<AccessMode>,761762 /// Minting allowance.763 ///764 /// * Default - **false**.765 pub mint_mode: Option<bool>,766767 /// Permissions for nesting.768 ///769 /// * Default770 /// - `token_owner` - **false**771 /// - `collection_admin` - **false**772 /// - `restricted` - **None**773 pub nesting: Option<NestingPermissions>,774}775776impl CollectionPermissions {777 /// Get effective value for [`access`](self.access).778 pub fn access(&self) -> AccessMode {779 self.access.unwrap_or(AccessMode::Normal)780 }781782 /// Get effective value for [`mint_mode`](self.mint_mode).783 pub fn mint_mode(&self) -> bool {784 self.mint_mode.unwrap_or(false)785 }786787 /// Get effective value for [`nesting`](self.nesting).788 pub fn nesting(&self) -> &NestingPermissions {789 static DEFAULT: NestingPermissions = NestingPermissions {790 token_owner: false,791 collection_admin: false,792 restricted: None,793 #[cfg(feature = "runtime-benchmarks")]794 permissive: false,795 };796 self.nesting.as_ref().unwrap_or(&DEFAULT)797 }798}799800/// Inner set for collections allowed to nest.801type OwnerRestrictedSetInner = BoundedBTreeSet<CollectionId, ConstU32<16>>;802803/// Wraper for collections set allowing nest.804#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]805#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]806#[derivative(Debug)]807pub struct OwnerRestrictedSet(808 #[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]809 #[derivative(Debug(format_with = "bounded::set_debug"))]810 pub OwnerRestrictedSetInner,811);812813impl OwnerRestrictedSet {814 /// Create new set.815 pub fn new() -> Self {816 Self(Default::default())817 }818}819impl Default for OwnerRestrictedSet {820 fn default() -> Self {821 Self::new()822 }823}824impl core::ops::Deref for OwnerRestrictedSet {825 type Target = OwnerRestrictedSetInner;826 fn deref(&self) -> &Self::Target {827 &self.0828 }829}830impl core::ops::DerefMut for OwnerRestrictedSet {831 fn deref_mut(&mut self) -> &mut Self::Target {832 &mut self.0833 }834}835836/// Part of collection permissions, if set, defines who is able to nest tokens into other tokens.837#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]838#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]839#[derivative(Debug)]840pub struct NestingPermissions {841 /// Owner of token can nest tokens under it.842 pub token_owner: bool,843 /// Admin of token collection can nest tokens under token.844 pub collection_admin: bool,845 /// If set - only tokens from specified collections can be nested.846 pub restricted: Option<OwnerRestrictedSet>,847848 #[cfg(feature = "runtime-benchmarks")]849 /// Anyone can nest tokens, mutually exclusive with `token_owner`, `admin`.850 pub permissive: bool,851}852853/// Enum denominating how often can sponsoring occur if it is enabled.854///855/// Used for [`collection limits`](CollectionLimits).856#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]857#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]858pub enum SponsoringRateLimit {859 /// Sponsoring is disabled, and the collection sponsor will not pay for transactions860 SponsoringDisabled,861 /// Once per how many blocks can sponsorship of a transaction type occur862 Blocks(u32),863}864865/// Data used to describe an NFT at creation.866#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]867#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]868#[derivative(Debug)]869pub struct CreateNftData {870 /// Key-value pairs used to describe the token as metadata871 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]872 #[derivative(Debug(format_with = "bounded::vec_debug"))]873 /// Properties that wil be assignet to created item.874 pub properties: CollectionPropertiesVec,875}876877/// Data used to describe a Fungible token at creation.878#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]879#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]880pub struct CreateFungibleData {881 /// Number of fungible coins minted882 pub value: u128,883}884885/// Data used to describe a Refungible token at creation.886#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]887#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]888#[derivative(Debug)]889pub struct CreateReFungibleData {890 /// Number of pieces the RFT is split into891 pub pieces: u128,892893 /// Key-value pairs used to describe the token as metadata894 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]895 #[derivative(Debug(format_with = "bounded::vec_debug"))]896 pub properties: CollectionPropertiesVec,897}898899// TODO: remove this.900#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]901#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]902pub enum MetaUpdatePermission {903 ItemOwner,904 Admin,905 None,906}907908/// Enum holding data used for creation of all three item types.909/// Unified data for create item.910#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]911#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]912pub enum CreateItemData {913 /// Data for create NFT.914 NFT(CreateNftData),915 /// Data for create Fungible item.916 Fungible(CreateFungibleData),917 /// Data for create ReFungible item.918 ReFungible(CreateReFungibleData),919}920921/// Extended data for create NFT.922#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]923#[derivative(Debug)]924pub struct CreateNftExData<CrossAccountId> {925 /// Properties that wil be assignet to created item.926 #[derivative(Debug(format_with = "bounded::vec_debug"))]927 pub properties: CollectionPropertiesVec,928929 /// Owner of creating item.930 pub owner: CrossAccountId,931}932933/// Extended data for create ReFungible item.934#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]935#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]936pub struct CreateRefungibleExMultipleOwners<CrossAccountId> {937 #[derivative(Debug(format_with = "bounded::map_debug"))]938 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,939 #[derivative(Debug(format_with = "bounded::vec_debug"))]940 pub properties: CollectionPropertiesVec,941}942943/// Extended data for create ReFungible item.944#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]945#[derivative(Debug(bound = "CrossAccountId: fmt::Debug"))]946pub struct CreateRefungibleExSingleOwner<CrossAccountId> {947 pub user: CrossAccountId,948 pub pieces: u128,949 #[derivative(Debug(format_with = "bounded::vec_debug"))]950 pub properties: CollectionPropertiesVec,951}952953/// Unified extended data for creating item.954#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]955#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]956pub enum CreateItemExData<CrossAccountId> {957 /// Extended data for create NFT.958 NFT(959 #[derivative(Debug(format_with = "bounded::vec_debug"))]960 BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,961 ),962963 /// Extended data for create Fungible item.964 Fungible(965 #[derivative(Debug(format_with = "bounded::map_debug"))]966 BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,967 ),968969 /// Extended data for create ReFungible item in case of970 /// many tokens, each may have only one owner971 RefungibleMultipleItems(972 #[derivative(Debug(format_with = "bounded::vec_debug"))]973 BoundedVec<CreateRefungibleExSingleOwner<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,974 ),975976 /// Extended data for create ReFungible item in case of977 /// single token, which may have many owners978 RefungibleMultipleOwners(CreateRefungibleExMultipleOwners<CrossAccountId>),979}980981impl From<CreateNftData> for CreateItemData {982 fn from(item: CreateNftData) -> Self {983 CreateItemData::NFT(item)984 }985}986987impl From<CreateReFungibleData> for CreateItemData {988 fn from(item: CreateReFungibleData) -> Self {989 CreateItemData::ReFungible(item)990 }991}992993impl From<CreateFungibleData> for CreateItemData {994 fn from(item: CreateFungibleData) -> Self {995 CreateItemData::Fungible(item)996 }997}998999/// Token's address, dictated by its collection and token IDs.1000#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]1001#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1002// todo possibly rename to be used generally as an address pair1003pub struct TokenChild {1004 /// Token id.1005 pub token: TokenId,10061007 /// Collection id.1008 pub collection: CollectionId,1009}10101011/// Collection statistics.1012#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]1013#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1014pub struct CollectionStats {1015 /// Number of created items.1016 pub created: u32,10171018 /// Number of burned items.1019 pub destroyed: u32,10201021 /// Number of current items.1022 pub alive: u32,1023}10241025/// This type works like [`PhantomData`] but supports generating _scale-info_ descriptions to generate node metadata.1026#[derive(Encode, Decode, Clone, Debug)]1027#[cfg_attr(feature = "std", derive(PartialEq))]1028pub struct PhantomType<T>(core::marker::PhantomData<T>);10291030impl<T: TypeInfo + 'static> TypeInfo for PhantomType<T> {1031 type Identity = PhantomType<T>;10321033 fn type_info() -> scale_info::Type {1034 use scale_info::{1035 Type, Path,1036 build::{FieldsBuilder, UnnamedFields},1037 form::MetaForm,1038 type_params,1039 };1040 Type::builder()1041 .path(Path::new("up_data_structs", "PhantomType"))1042 .type_params(type_params!(T))1043 .composite(1044 <FieldsBuilder<MetaForm, UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()),1045 )1046 }1047}1048impl<T> MaxEncodedLen for PhantomType<T> {1049 fn max_encoded_len() -> usize {1050 01051 }1052}10531054/// Bounded vector of bytes.1055pub type BoundedBytes<S> = BoundedVec<u8, S>;10561057/// Extra properties for external collections.1058pub type AuxPropertyValue = BoundedBytes<ConstU32<MAX_AUX_PROPERTY_VALUE_LENGTH>>;10591060/// Property key.1061pub type PropertyKey = BoundedBytes<ConstU32<MAX_PROPERTY_KEY_LENGTH>>;10621063/// Property value.1064pub type PropertyValue = BoundedBytes<ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;10651066/// Property permission.1067#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone, Default)]1068#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1069pub struct PropertyPermission {1070 /// Permission to change the property and property permission.1071 ///1072 /// If it **false** then you can not change corresponding property even if [`collection_admin`] and [`token_owner`] are **true**.1073 pub mutable: bool,10741075 /// Change permission for the collection administrator.1076 pub collection_admin: bool,10771078 /// Permission to change the property for the owner of the token.1079 pub token_owner: bool,1080}10811082impl PropertyPermission {1083 /// Creates mutable property permission but changes restricted for collection admin and token owner.1084 pub fn none() -> Self {1085 Self {1086 mutable: true,1087 collection_admin: false,1088 token_owner: false,1089 }1090 }1091}10921093/// Property is simpl key-value record.1094#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, MaxEncodedLen)]1095#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1096pub struct Property {1097 /// Property key.1098 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1099 pub key: PropertyKey,11001101 /// Property value.1102 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1103 pub value: PropertyValue,1104}11051106impl From<Property> for (PropertyKey, PropertyValue) {1107 fn from(value: Property) -> Self {1108 (value.key, value.value)1109 }1110}11111112/// Record for proprty key permission.1113#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]1114#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1115pub struct PropertyKeyPermission {1116 /// Key.1117 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1118 pub key: PropertyKey,11191120 /// Permission.1121 pub permission: PropertyPermission,1122}11231124impl From<PropertyKeyPermission> for (PropertyKey, PropertyPermission) {1125 fn from(value: PropertyKeyPermission) -> Self {1126 (value.key, value.permission)1127 }1128}11291130/// Errors for properties actions.1131#[derive(Debug)]1132pub enum PropertiesError {1133 /// The space allocated for properties has run out.1134 ///1135 /// * Limit for colection - [`MAX_COLLECTION_PROPERTIES_SIZE`].1136 /// * Limit for token - [`MAX_TOKEN_PROPERTIES_SIZE`].1137 NoSpaceForProperty,11381139 /// The property limit has been reached.1140 ///1141 /// * Limit - [`MAX_PROPERTIES_PER_ITEM`].1142 PropertyLimitReached,11431144 /// Property key contains not allowed character.1145 InvalidCharacterInPropertyKey,11461147 /// Property key length is too long.1148 ///1149 /// * Limit - [`MAX_PROPERTY_KEY_LENGTH`].1150 PropertyKeyIsTooLong,11511152 /// Property key is empty.1153 EmptyPropertyKey,1154}11551156/// Token owner error: it could be either `NotFound` ot `MultipleOwners`.1157#[derive(Debug)]1158pub enum TokenOwnerError {1159 NotFound,1160 MultipleOwners,1161}11621163/// Marker for scope of property.1164///1165/// Scoped property can't be changed by user. Used for external collections.1166#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Clone, Copy)]1167pub enum PropertyScope {1168 None,1169 Rmrk,1170}11711172impl PropertyScope {1173 pub fn prefix(&self) -> &'static [u8] {1174 match self {1175 Self::None => b"",1176 Self::Rmrk => b"rmrk:",1177 }1178 }1179 /// Apply scope to property key.1180 pub fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {1181 let prefix = self.prefix();1182 if prefix == b"" {1183 return Ok(key);1184 }1185 [prefix, key.as_slice()]1186 .concat()1187 .try_into()1188 .map_err(|_| PropertiesError::PropertyKeyIsTooLong)1189 }1190}11911192/// Trait for operate with properties.1193pub trait TrySetProperty: Sized {1194 type Value;11951196 /// Try to set property with scope.1197 fn try_scoped_set(1198 &mut self,1199 scope: PropertyScope,1200 key: PropertyKey,1201 value: Self::Value,1202 ) -> Result<Option<Self::Value>, PropertiesError>;12031204 /// Try to set property with scope from iterator.1205 fn try_scoped_set_from_iter<I, KV>(1206 &mut self,1207 scope: PropertyScope,1208 iter: I,1209 ) -> Result<(), PropertiesError>1210 where1211 I: Iterator<Item = KV>,1212 KV: Into<(PropertyKey, Self::Value)>,1213 {1214 for kv in iter {1215 let (key, value) = kv.into();1216 self.try_scoped_set(scope, key, value)?;1217 }12181219 Ok(())1220 }12211222 /// Try to set property.1223 fn try_set(1224 &mut self,1225 key: PropertyKey,1226 value: Self::Value,1227 ) -> Result<Option<Self::Value>, PropertiesError> {1228 self.try_scoped_set(PropertyScope::None, key, value)1229 }12301231 /// Try to set property from iterator.1232 fn try_set_from_iter<I, KV>(&mut self, iter: I) -> Result<(), PropertiesError>1233 where1234 I: Iterator<Item = KV>,1235 KV: Into<(PropertyKey, Self::Value)>,1236 {1237 self.try_scoped_set_from_iter(PropertyScope::None, iter)1238 }1239}12401241/// Wrapped map for storing properties.1242#[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]1243#[derivative(Default(bound = ""))]1244pub struct PropertiesMap<Value>(1245 BoundedBTreeMap<PropertyKey, Value, ConstU32<MAX_PROPERTIES_PER_ITEM>>,1246);12471248impl<Value> PropertiesMap<Value> {1249 /// Create new property map.1250 pub fn new() -> Self {1251 Self(BoundedBTreeMap::new())1252 }12531254 /// Remove property from map.1255 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<Value>, PropertiesError> {1256 Self::check_property_key(key)?;12571258 Ok(self.0.remove(key))1259 }12601261 /// Get property with appropriate key from map.1262 pub fn get(&self, key: &PropertyKey) -> Option<&Value> {1263 self.0.get(key)1264 }12651266 /// Check if map contains key.1267 pub fn contains_key(&self, key: &PropertyKey) -> bool {1268 self.0.contains_key(key)1269 }12701271 /// Check if map contains key with key validation.1272 fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {1273 if key.is_empty() {1274 return Err(PropertiesError::EmptyPropertyKey);1275 }12761277 for byte in key.as_slice().iter() {1278 let byte = *byte;12791280 if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' && byte != b'.' {1281 return Err(PropertiesError::InvalidCharacterInPropertyKey);1282 }1283 }12841285 Ok(())1286 }12871288 pub fn values(&self) -> impl Iterator<Item = &Value> {1289 self.0.values()1290 }12911292 pub fn iter(&self) -> impl Iterator<Item = (&PropertyKey, &Value)> {1293 self.0.iter()1294 }1295}12961297impl<Value> IntoIterator for PropertiesMap<Value> {1298 type Item = (PropertyKey, Value);1299 type IntoIter = <1300 BoundedBTreeMap<1301 PropertyKey,1302 Value,1303 ConstU32<MAX_PROPERTIES_PER_ITEM>1304 > as IntoIterator1305 >::IntoIter;13061307 fn into_iter(self) -> Self::IntoIter {1308 self.0.into_iter()1309 }1310}13111312impl<Value> TrySetProperty for PropertiesMap<Value> {1313 type Value = Value;13141315 fn try_scoped_set(1316 &mut self,1317 scope: PropertyScope,1318 key: PropertyKey,1319 value: Self::Value,1320 ) -> Result<Option<Self::Value>, PropertiesError> {1321 Self::check_property_key(&key)?;13221323 let key = scope.apply(key)?;1324 self.01325 .try_insert(key, value)1326 .map_err(|_| PropertiesError::PropertyLimitReached)1327 }1328}13291330/// Alias for property permissions map.1331pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;13321333fn slice_size(data: &[u8]) -> u32 {1334 scoped_slice_size(PropertyScope::None, data)1335}1336fn scoped_slice_size(scope: PropertyScope, data: &[u8]) -> u32 {1337 use codec::Compact;1338 let prefix = scope.prefix();1339 <Compact<u32>>::encoded_size(&Compact(data.len() as u32 + prefix.len() as u32)) as u321340 + data.len() as u321341 + prefix.len() as u321342}13431344/// Wrapper for properties map with consumed space control.1345#[derive(Encode, Decode, TypeInfo, Clone, PartialEq)]1346pub struct Properties<const S: u32> {1347 map: PropertiesMap<PropertyValue>,1348 consumed_space: u32,1349 // May be not zero, previously served as a current S generic1350 _reserved: u32,1351}13521353impl<const S: u32> MaxEncodedLen for Properties<S> {1354 fn max_encoded_len() -> usize {1355 // len of map + len of consumed_space + len of space_limit1356 u32::max_encoded_len() * 3 + S as usize1357 }1358}13591360impl<const S: u32> Default for Properties<S> {1361 fn default() -> Self {1362 Self::new()1363 }1364}13651366impl<const S: u32> Properties<S> {1367 /// Create new properies container.1368 pub fn new() -> Self {1369 Self {1370 map: PropertiesMap::new(),1371 consumed_space: 0,1372 _reserved: 0,1373 }1374 }13751376 /// Remove propery with appropiate key.1377 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<PropertyValue>, PropertiesError> {1378 let value = self.map.remove(key)?;13791380 if let Some(ref value) = value {1381 let kv_len = slice_size(key) + slice_size(value);1382 self.consumed_space = self.consumed_space.saturating_sub(kv_len);1383 }13841385 Ok(value)1386 }13871388 /// Get property with appropriate key.1389 pub fn get(&self, key: &PropertyKey) -> Option<&PropertyValue> {1390 self.map.get(key)1391 }13921393 /// Recomputes the consumed space for the current properties state.1394 /// Needed to repair a token due to a bug fixed in the [PR #733](https://github.com/UniqueNetwork/unique-chain/pull/773).1395 pub fn recompute_consumed_space(&mut self) {1396 self.consumed_space = self1397 .map1398 .iter()1399 .map(|(key, value)| slice_size(key) + slice_size(value))1400 .sum();1401 }1402}14031404impl<const S: u32> IntoIterator for Properties<S> {1405 type Item = (PropertyKey, PropertyValue);1406 type IntoIter = <PropertiesMap<PropertyValue> as IntoIterator>::IntoIter;14071408 fn into_iter(self) -> Self::IntoIter {1409 self.map.into_iter()1410 }1411}14121413impl<const S: u32> TrySetProperty for Properties<S> {1414 type Value = PropertyValue;14151416 fn try_scoped_set(1417 &mut self,1418 scope: PropertyScope,1419 key: PropertyKey,1420 value: Self::Value,1421 ) -> Result<Option<Self::Value>, PropertiesError> {1422 let key_size = scoped_slice_size(scope, &key);1423 let value_size = slice_size(&value);14241425 if self.consumed_space + value_size + key_size > S && !cfg!(feature = "runtime-benchmarks")1426 {1427 return Err(PropertiesError::NoSpaceForProperty);1428 }14291430 let old_value = self.map.try_scoped_set(scope, key, value)?;14311432 if let Some(old_value) = old_value.as_ref() {1433 let old_value_size = slice_size(old_value);1434 self.consumed_space = self.consumed_space.saturating_sub(old_value_size) + value_size;1435 } else {1436 self.consumed_space += key_size + value_size;1437 }14381439 Ok(old_value)1440 }1441}14421443pub type CollectionProperties = Properties<MAX_COLLECTION_PROPERTIES_SIZE>;1444pub type TokenProperties = Properties<MAX_TOKEN_PROPERTIES_SIZE>;runtime/common/config/xcm/foreignassets.rsdiffbeforeafterboth--- a/runtime/common/config/xcm/foreignassets.rs
+++ b/runtime/common/config/xcm/foreignassets.rs
@@ -65,7 +65,7 @@
return ConvertAssetId::convert_ref(AssetIds::NativeAssetId(NativeCurrency::Here));
}
- match XcmForeignAssetIdMapping::<Runtime>::get_currency_id(id.clone()) {
+ match XcmForeignAssetIdMapping::<Runtime>::get_currency_id(*id) {
Some(AssetIds::ForeignAssetId(foreign_asset_id)) => {
ConvertAssetId::convert_ref(AssetIds::ForeignAssetId(foreign_asset_id))
}
@@ -206,9 +206,7 @@
return Some(AssetIds::NativeAssetId(NativeCurrency::Parent));
}
- if let Some(currency_id) =
- XcmForeignAssetIdMapping::<Runtime>::get_currency_id(location.clone())
- {
+ if let Some(currency_id) = XcmForeignAssetIdMapping::<Runtime>::get_currency_id(location) {
return Some(currency_id);
}
runtime/common/ethereum/precompiles/mod.rsdiffbeforeafterboth--- a/runtime/common/ethereum/precompiles/mod.rs
+++ b/runtime/common/ethereum/precompiles/mod.rs
@@ -37,6 +37,16 @@
[hash(1), hash(20482)]
}
}
+
+impl<R> Default for UniquePrecompiles<R>
+where
+ R: pallet_evm::Config,
+{
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
impl<R> PrecompileSet for UniquePrecompiles<R>
where
R: pallet_evm::Config,
runtime/common/ethereum/precompiles/sr25519.rsdiffbeforeafterboth--- a/runtime/common/ethereum/precompiles/sr25519.rs
+++ b/runtime/common/ethereum/precompiles/sr25519.rs
@@ -64,7 +64,7 @@
// Parse arguments
let public: sr25519::Public =
- sr25519::Public::unchecked_from(input.read::<H256>(gasometer)?).into();
+ sr25519::Public::unchecked_from(input.read::<H256>(gasometer)?);
let signature_bytes: Vec<u8> = input.read::<Bytes>(gasometer)?.into();
let message: Vec<u8> = input.read::<Bytes>(gasometer)?.into();
runtime/common/ethereum/precompiles/utils/data.rsdiffbeforeafterboth--- a/runtime/common/ethereum/precompiles/utils/data.rs
+++ b/runtime/common/ethereum/precompiles/utils/data.rs
@@ -60,7 +60,7 @@
}
impl Into<Vec<u8>> for Bytes {
- fn into(self: Self) -> Vec<u8> {
+ fn into(self) -> Vec<u8> {
self.0
}
}
runtime/common/ethereum/precompiles/utils/mod.rsdiffbeforeafterboth--- a/runtime/common/ethereum/precompiles/utils/mod.rs
+++ b/runtime/common/ethereum/precompiles/utils/mod.rs
@@ -73,7 +73,6 @@
}
}
- #[must_use]
/// Check that a function call is compatible with the context it is
/// called into.
pub fn check_function_modifier(
runtime/common/ethereum/sponsoring.rsdiffbeforeafterboth--- a/runtime/common/ethereum/sponsoring.rs
+++ b/runtime/common/ethereum/sponsoring.rs
@@ -78,7 +78,7 @@
let token_id: TokenId = token_id.try_into().ok()?;
withdraw_set_token_property::<T>(
&collection,
- &who,
+ who,
&token_id,
key.len() + value.len(),
)
@@ -88,7 +88,7 @@
ERC721UniqueExtensionsCall::Transfer { token_id, .. },
) => {
let token_id: TokenId = token_id.try_into().ok()?;
- withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)
+ withdraw_transfer::<T>(&collection, who, &token_id).map(|()| sponsor)
}
UniqueNFTCall::ERC721UniqueMintable(
ERC721UniqueMintableCall::Mint { .. }
@@ -97,7 +97,7 @@
| ERC721UniqueMintableCall::MintWithTokenUriCheckId { .. },
) => withdraw_create_item::<T>(
&collection,
- &who,
+ who,
&CreateItemData::NFT(CreateNftData::default()),
)
.map(|()| sponsor),
runtime/common/ethereum/sponsoring/refungible.rsdiffbeforeafterboth--- a/runtime/common/ethereum/sponsoring/refungible.rs
+++ b/runtime/common/ethereum/sponsoring/refungible.rs
@@ -16,7 +16,6 @@
//! Implements EVM sponsoring logic via TransactionValidityHack
-use core::convert::TryInto;
use pallet_common::CollectionHandle;
use pallet_evm::account::CrossAccountId;
use pallet_fungible::Config as FungibleConfig;
@@ -95,7 +94,7 @@
..
} => {
let token_id = TokenId::try_from(token_id).ok()?;
- withdraw_set_token_property::<T>(&collection, &who, &token_id, key.len() + value.len())
+ withdraw_set_token_property::<T>(&collection, who, &token_id, key.len() + value.len())
}
}
}
@@ -242,7 +241,7 @@
MintCross { .. } => withdraw_create_item::<T>(
&collection,
- &who,
+ who,
&CreateItemData::NFT(CreateNftData::default()),
),
@@ -250,7 +249,7 @@
| TransferFromCross { token_id, .. }
| Transfer { token_id, .. } => {
let token_id = TokenId::try_from(token_id).ok()?;
- withdraw_transfer::<T>(&collection, &who, &token_id)
+ withdraw_transfer::<T>(&collection, who, &token_id)
}
}
}
@@ -275,7 +274,7 @@
| MintWithTokenUri { .. }
| MintWithTokenUriCheckId { .. } => withdraw_create_item::<T>(
&collection,
- &who,
+ who,
&CreateItemData::NFT(CreateNftData::default()),
),
}
@@ -311,18 +310,15 @@
Transfer { .. } => {
let RefungibleTokenHandle(handle, token_id) = token;
- let token_id = token_id.try_into().ok()?;
- withdraw_transfer::<T>(&handle, &who, &token_id)
+ withdraw_transfer::<T>(&handle, who, &token_id)
}
TransferFrom { from, .. } => {
let RefungibleTokenHandle(handle, token_id) = token;
- let token_id = token_id.try_into().ok()?;
let from = T::CrossAccountId::from_eth(from);
withdraw_transfer::<T>(&handle, &from, &token_id)
}
Approve { .. } => {
let RefungibleTokenHandle(handle, token_id) = token;
- let token_id = token_id.try_into().ok()?;
withdraw_approve::<T>(&handle, who.as_sub(), &token_id)
}
}
@@ -351,13 +347,11 @@
TransferCross { .. } | TransferFromCross { .. } => {
let RefungibleTokenHandle(handle, token_id) = token;
- let token_id = token_id.try_into().ok()?;
- withdraw_transfer::<T>(&handle, &who, &token_id)
+ withdraw_transfer::<T>(&handle, who, &token_id)
}
ApproveCross { .. } => {
let RefungibleTokenHandle(handle, token_id) = token;
- let token_id = token_id.try_into().ok()?;
withdraw_approve::<T>(&handle, who.as_sub(), &token_id)
}
}
runtime/common/mod.rsdiffbeforeafterboth--- a/runtime/common/mod.rs
+++ b/runtime/common/mod.rs
@@ -204,10 +204,7 @@
&[],
);
- let should_upgrade = match version {
- None => true,
- Some(_) => false,
- };
+ let should_upgrade = version.is_none();
if should_upgrade {
log::info!(
@@ -220,7 +217,7 @@
.cloned()
.filter_map(|authority_id| {
weight.saturating_accrue(<Runtime as frame_system::Config>::DbWeight::get().reads_writes(1, 1));
- let vec = authority_id.clone().to_raw_vec();
+ let vec = authority_id.to_raw_vec();
let slice = vec.as_slice();
let array: Option<[u8; 32]> = match slice.try_into() {
Ok(a) => Some(a),
@@ -248,20 +245,20 @@
.into_iter()
.map(|(acc, aura)| {
(
- acc.clone(), // account id
- acc, // validator id
- SessionKeys { aura: aura.clone() }, // session keys
+ acc.clone(), // account id
+ acc, // validator id
+ SessionKeys { aura }, // session keys
)
})
.collect::<Vec<_>>();
- for (account, val, keys) in keys.iter().cloned() {
+ for (account, val, keys) in keys.iter() {
for id in <Runtime as pallet_session::Config>::Keys::key_ids() {
- <pallet_session::KeyOwner<Runtime>>::insert((*id, keys.get_raw(*id)), &val)
+ <pallet_session::KeyOwner<Runtime>>::insert((*id, keys.get_raw(*id)), val)
}
- <pallet_session::NextKeys<Runtime>>::insert(&val, &keys);
+ <pallet_session::NextKeys<Runtime>>::insert(val, keys);
// todo exercise caution, the following is taken from genesis
- if frame_system::Pallet::<Runtime>::inc_consumers_without_limit(&account)
+ if frame_system::Pallet::<Runtime>::inc_consumers_without_limit(account)
.is_err()
{
log::warn!(
@@ -271,7 +268,7 @@
// genesis) so it's really not a big deal and we assume that the user wants to
// do this since it's the only way a non-endowed account can contain a session
// key.
- frame_system::Pallet::<Runtime>::inc_providers(&account);
+ frame_system::Pallet::<Runtime>::inc_providers(account);
}
}
runtime/common/runtime_apis.rsdiffbeforeafterboth--- a/runtime/common/runtime_apis.rs
+++ b/runtime/common/runtime_apis.rs
@@ -84,7 +84,7 @@
fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {
let budget = up_data_structs::budget::Value::new(10);
- Ok(<pallet_structure::Pallet<Runtime>>::find_topmost_owner(collection, token, &budget)?)
+ <pallet_structure::Pallet<Runtime>>::find_topmost_owner(collection, token, &budget)
}
fn token_children(collection: CollectionId, token: TokenId) -> Result<Vec<TokenChild>, DispatchError> {
Ok(<pallet_nonfungible::Pallet<Runtime>>::token_children_ids(collection, token))
runtime/common/sponsoring.rsdiffbeforeafterboth--- a/runtime/common/sponsoring.rs
+++ b/runtime/common/sponsoring.rs
@@ -240,7 +240,7 @@
withdraw_set_token_property(
&collection,
&T::CrossAccountId::from_sub(who.clone()),
- &token_id,
+ token_id,
// No overflow may happen, as data larger than usize can't reach here
properties.iter().map(|p| p.key.len() + p.value.len()).sum(),
)
test-pallets/utils/src/lib.rsdiffbeforeafterboth--- a/test-pallets/utils/src/lib.rs
+++ b/test-pallets/utils/src/lib.rs
@@ -170,7 +170,7 @@
fn ensure_origin_and_enabled(origin: OriginFor<T>) -> DispatchResult {
ensure_signed(origin)?;
<Enabled<T>>::get()
- .then(|| ())
+ .then_some(())
.ok_or(<Error<T>>::TestPalletDisabled.into())
}
}