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.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//! # Nonfungible Pallet18//!19//! The Nonfungible pallet provides functionality for handling nonfungible collections and tokens.20//!21//! - [`Config`]22//! - [`NonfungibleHandle`]23//! - [`Pallet`]24//! - [`CommonWeights`](common::CommonWeights)25//!26//! ## Overview27//!28//! The Nonfungible pallet provides functions for:29//!30//! - NFT collection creation and removal31//! - Minting and burning of NFT tokens32//! - Retrieving account balances33//! - Transfering NFT tokens34//! - Setting and checking allowance for NFT tokens35//! - Setting properties and permissions for NFT collections and tokens36//! - Nesting and unnesting tokens37//!38//! ### Terminology39//!40//! - **NFT token:** Non fungible token.41//!42//! - **NFT Collection:** A collection of NFT tokens. All NFT tokens are part of a collection.43//! Each collection can define it's own properties, properties for it's tokens and set of permissions.44//!45//! - **Balance:** Number of NFT tokens owned by an account46//!47//! - **Allowance:** NFT tokens owned by one account that another account is allowed to make operations on48//!49//! - **Burning:** The process of “deleting” a token from a collection and from50//! an account balance of the owner.51//!52//! - **Nesting:** Setting up parent-child relationship between tokens. Nested tokens are inhereting53//! owner from their parent. There could be multiple levels of nesting. Token couldn't be nested in54//! it's child token i.e. parent-child relationship graph shouldn't have cycles.55//!56//! - **Properties:** Key-Values pairs. Token properties are attached to a token. Collection properties are57//! attached to a collection. Set of permissions could be defined for each property.58//!59//! ### Implementations60//!61//! The Nonfungible pallet provides implementations for the following traits. If these traits provide62//! the functionality that you need, then you can avoid coupling with the Nonfungible pallet.63//!64//! - [`CommonWeightInfo`](pallet_common::CommonWeightInfo): Functions for retrieval of transaction weight65//! - [`CommonCollectionOperations`](pallet_common::CommonCollectionOperations): Functions for dealing66//! with collections67//!68//! ## Interface69//!70//! ### Dispatchable Functions71//!72//! - `init_collection` - Create NFT collection. NFT collection can be configured to allow or deny access for73//! some accounts.74//! - `destroy_collection` - Destroy exising NFT collection. There should be no tokens in the collection.75//! - `burn` - Burn NFT token owned by account.76//! - `transfer` - Transfer NFT token. Transfers should be enabled for NFT collection.77//! Nests the NFT token if it is sent to another token.78//! - `create_item` - Mint NFT token in collection. Sender should have permission to mint tokens.79//! - `set_allowance` - Set allowance for another account.80//! - `set_token_property` - Set token property value.81//! - `delete_token_property` - Remove property from the token.82//! - `set_collection_properties` - Set collection properties.83//! - `delete_collection_properties` - Remove properties from the collection.84//! - `set_property_permission` - Set collection property permission.85//! - `set_token_property_permissions` - Set token property permissions.86//!87//! ## Assumptions88//!89//! * To perform operations on tokens sender should be in collection's allow list if collection access mode is `AllowList`.9091#![cfg_attr(not(feature = "std"), no_std)]9293use erc::ERC721Events;94use evm_coder::ToLog;95use frame_support::{96 BoundedVec, ensure, fail, transactional,97 storage::with_transaction,98 pallet_prelude::DispatchResultWithPostInfo,99 pallet_prelude::Weight,100 dispatch::{PostDispatchInfo, Pays},101};102use up_data_structs::{103 AccessMode, CollectionId, CollectionFlags, CustomDataLimit, TokenId, CreateCollectionData,104 CreateNftExData, mapping::TokenAddressMapping, budget::Budget, Property, PropertyKey,105 PropertyValue, PropertyKeyPermission, PropertyScope, TrySetProperty, TokenChild,106 AuxPropertyValue, PropertiesPermissionMap, TokenProperties as TokenPropertiesT,107};108use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};109use pallet_common::{110 Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, CollectionHandle,111 eth::collection_id_to_address, SelfWeightOf as PalletCommonWeightOf,112 weights::WeightInfo as CommonWeightInfo, helpers::add_weight_to_post_info,113};114use pallet_structure::{Pallet as PalletStructure, Error as StructureError};115use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};116use sp_core::{Get, H160};117use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};118use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};119use core::ops::Deref;120use codec::{Encode, Decode, MaxEncodedLen};121use scale_info::TypeInfo;122123pub use pallet::*;124use weights::WeightInfo;125#[cfg(feature = "runtime-benchmarks")]126pub mod benchmarking;127pub mod common;128pub mod erc;129pub mod weights;130131pub type CreateItemData<T> = CreateNftExData<<T as pallet_evm::Config>::CrossAccountId>;132pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;133134/// Token data, stored independently from other data used to describe it135/// for the convenience of database access. Notably contains the owner account address.136#[struct_versioning::versioned(version = 2, upper)]137#[derive(Encode, Decode, TypeInfo, MaxEncodedLen)]138pub struct ItemData<CrossAccountId> {139 #[version(..2)]140 pub const_data: BoundedVec<u8, CustomDataLimit>,141142 #[version(..2)]143 pub variable_data: BoundedVec<u8, CustomDataLimit>,144145 pub owner: CrossAccountId,146}147148#[frame_support::pallet]149pub mod pallet {150 use super::*;151 use frame_support::{152 Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key, traits::StorageVersion,153 };154 use up_data_structs::{CollectionId, TokenId};155 use super::weights::WeightInfo;156157 #[pallet::error]158 pub enum Error<T> {159 /// Not Nonfungible item data used to mint in Nonfungible collection.160 NotNonfungibleDataUsedToMintFungibleCollectionToken,161 /// Used amount > 1 with NFT162 NonfungibleItemsHaveNoAmount,163 /// Unable to burn NFT with children164 CantBurnNftWithChildren,165 }166167 #[pallet::config]168 pub trait Config:169 frame_system::Config170 + pallet_common::Config171 + pallet_structure::Config172 + pallet_evm::Config173 {174 type WeightInfo: WeightInfo;175 }176177 const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);178179 #[pallet::pallet]180 #[pallet::storage_version(STORAGE_VERSION)]181 pub struct Pallet<T>(_);182183 /// Total amount of minted tokens in a collection.184 #[pallet::storage]185 pub type TokensMinted<T: Config> =186 StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;187188 /// Amount of burnt tokens in a collection.189 #[pallet::storage]190 pub type TokensBurnt<T: Config> =191 StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;192193 /// Token data, used to partially describe a token.194 #[pallet::storage]195 pub type TokenData<T: Config> = StorageNMap<196 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),197 Value = ItemData<T::CrossAccountId>,198 QueryKind = OptionQuery,199 >;200201 /// Map of key-value pairs, describing the metadata of a token.202 #[pallet::storage]203 #[pallet::getter(fn token_properties)]204 pub type TokenProperties<T: Config> = StorageNMap<205 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),206 Value = TokenPropertiesT,207 QueryKind = ValueQuery,208 >;209210 /// Custom data of a token that is serialized to bytes,211 /// primarily reserved for on-chain operations,212 /// normally obscured from the external users.213 ///214 /// Auxiliary properties are slightly different from215 /// usual [`TokenProperties`] due to an unlimited number216 /// and separately stored and written-to key-value pairs.217 ///218 /// Currently unused.219 #[pallet::storage]220 #[pallet::getter(fn token_aux_property)]221 pub type TokenAuxProperties<T: Config> = StorageNMap<222 Key = (223 Key<Twox64Concat, CollectionId>,224 Key<Twox64Concat, TokenId>,225 Key<Twox64Concat, PropertyScope>,226 Key<Twox64Concat, PropertyKey>,227 ),228 Value = AuxPropertyValue,229 QueryKind = OptionQuery,230 >;231232 /// Used to enumerate tokens owned by account.233 #[pallet::storage]234 pub type Owned<T: Config> = StorageNMap<235 Key = (236 Key<Twox64Concat, CollectionId>,237 Key<Blake2_128Concat, T::CrossAccountId>,238 Key<Twox64Concat, TokenId>,239 ),240 Value = bool,241 QueryKind = ValueQuery,242 >;243244 /// Used to enumerate token's children.245 #[pallet::storage]246 #[pallet::getter(fn token_children)]247 pub type TokenChildren<T: Config> = StorageNMap<248 Key = (249 Key<Twox64Concat, CollectionId>,250 Key<Twox64Concat, TokenId>,251 Key<Twox64Concat, (CollectionId, TokenId)>,252 ),253 Value = bool,254 QueryKind = ValueQuery,255 >;256257 /// Amount of tokens owned by an account in a collection.258 #[pallet::storage]259 pub type AccountBalance<T: Config> = StorageNMap<260 Key = (261 Key<Twox64Concat, CollectionId>,262 Key<Blake2_128Concat, T::CrossAccountId>,263 ),264 Value = u32,265 QueryKind = ValueQuery,266 >;267268 /// Allowance set by a token owner for another user to perform one of certain transactions on a token.269 #[pallet::storage]270 pub type Allowance<T: Config> = StorageNMap<271 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),272 Value = T::CrossAccountId,273 QueryKind = OptionQuery,274 >;275276 /// Operator set by a wallet owner that could perform certain transactions on all tokens in the wallet.277 #[pallet::storage]278 pub type CollectionAllowance<T: Config> = StorageNMap<279 Key = (280 Key<Twox64Concat, CollectionId>,281 Key<Blake2_128Concat, T::CrossAccountId>,282 Key<Blake2_128Concat, T::CrossAccountId>,283 ),284 Value = bool,285 QueryKind = ValueQuery,286 >;287288 #[pallet::genesis_config]289 pub struct GenesisConfig<T>(PhantomData<T>);290291 #[cfg(feature = "std")]292 impl<T: Config> Default for GenesisConfig<T> {293 fn default() -> Self {294 Self(Default::default())295 }296 }297298 #[pallet::genesis_build]299 impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {300 fn build(&self) {301 StorageVersion::new(1).put::<Pallet<T>>();302 }303 }304}305306pub struct NonfungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);307impl<T: Config> NonfungibleHandle<T> {308 pub fn cast(inner: pallet_common::CollectionHandle<T>) -> Self {309 Self(inner)310 }311 pub fn into_inner(self) -> pallet_common::CollectionHandle<T> {312 self.0313 }314 pub fn common_mut(&mut self) -> &mut pallet_common::CollectionHandle<T> {315 &mut self.0316 }317}318319impl<T: Config> WithRecorder<T> for NonfungibleHandle<T> {320 fn recorder(&self) -> &SubstrateRecorder<T> {321 self.0.recorder()322 }323 fn into_recorder(self) -> SubstrateRecorder<T> {324 self.0.into_recorder()325 }326}327impl<T: Config> Deref for NonfungibleHandle<T> {328 type Target = pallet_common::CollectionHandle<T>;329330 fn deref(&self) -> &Self::Target {331 &self.0332 }333}334335impl<T: Config> Pallet<T> {336 /// Get number of NFT tokens in collection.337 pub fn total_supply(collection: &NonfungibleHandle<T>) -> u32 {338 <TokensMinted<T>>::get(collection.id) - <TokensBurnt<T>>::get(collection.id)339 }340341 /// Check that NFT token exists.342 ///343 /// - `token`: Token ID.344 pub fn token_exists(collection: &NonfungibleHandle<T>, token: TokenId) -> bool {345 <TokenData<T>>::contains_key((collection.id, token))346 }347348 /// Set the token property with the scope.349 ///350 /// - `property`: Contains key-value pair.351 pub fn set_scoped_token_property(352 collection_id: CollectionId,353 token_id: TokenId,354 scope: PropertyScope,355 property: Property,356 ) -> DispatchResult {357 TokenProperties::<T>::try_mutate((collection_id, token_id), |properties| {358 properties.try_scoped_set(scope, property.key, property.value)359 })360 .map_err(<CommonError<T>>::from)?;361362 Ok(())363 }364365 /// Batch operation to set multiple properties with the same scope.366 pub fn set_scoped_token_properties(367 collection_id: CollectionId,368 token_id: TokenId,369 scope: PropertyScope,370 properties: impl Iterator<Item = Property>,371 ) -> DispatchResult {372 TokenProperties::<T>::try_mutate((collection_id, token_id), |stored_properties| {373 stored_properties.try_scoped_set_from_iter(scope, properties)374 })375 .map_err(<CommonError<T>>::from)?;376377 Ok(())378 }379380 /// Add or edit auxiliary data for the property.381 ///382 /// - `f`: function that adds or edits auxiliary data.383 pub fn try_mutate_token_aux_property<R, E>(384 collection_id: CollectionId,385 token_id: TokenId,386 scope: PropertyScope,387 key: PropertyKey,388 f: impl FnOnce(&mut Option<AuxPropertyValue>) -> Result<R, E>,389 ) -> Result<R, E> {390 <TokenAuxProperties<T>>::try_mutate((collection_id, token_id, scope, key), f)391 }392393 /// Remove auxiliary data for the property.394 pub fn remove_token_aux_property(395 collection_id: CollectionId,396 token_id: TokenId,397 scope: PropertyScope,398 key: PropertyKey,399 ) {400 <TokenAuxProperties<T>>::remove((collection_id, token_id, scope, key));401 }402403 /// Get all auxiliary data in a given scope.404 ///405 /// Returns iterator over Property Key - Data pairs.406 pub fn iterate_token_aux_properties(407 collection_id: CollectionId,408 token_id: TokenId,409 scope: PropertyScope,410 ) -> impl Iterator<Item = (PropertyKey, AuxPropertyValue)> {411 <TokenAuxProperties<T>>::iter_prefix((collection_id, token_id, scope))412 }413414 /// Get ID of the last minted token415 pub fn current_token_id(collection_id: CollectionId) -> TokenId {416 TokenId(<TokensMinted<T>>::get(collection_id))417 }418}419420// unchecked calls skips any permission checks421impl<T: Config> Pallet<T> {422 /// Create NFT collection423 ///424 /// `init_collection` will take non-refundable deposit for collection creation.425 ///426 /// - `data`: Contains settings for collection limits and permissions.427 pub fn init_collection(428 owner: T::CrossAccountId,429 payer: T::CrossAccountId,430 data: CreateCollectionData<T::AccountId>,431 flags: CollectionFlags,432 ) -> Result<CollectionId, DispatchError> {433 <PalletCommon<T>>::init_collection(owner, payer, data, flags)434 }435436 /// Destroy NFT collection437 ///438 /// `destroy_collection` will throw error if collection contains any tokens.439 /// Only owner can destroy collection.440 pub fn destroy_collection(441 collection: NonfungibleHandle<T>,442 sender: &T::CrossAccountId,443 ) -> DispatchResult {444 let id = collection.id;445446 if Self::collection_has_tokens(id) {447 return Err(<CommonError<T>>::CantDestroyNotEmptyCollection.into());448 }449450 // =========451452 PalletCommon::destroy_collection(collection.0, sender)?;453454 let _ = <TokenData<T>>::clear_prefix((id,), u32::MAX, None);455 let _ = <TokenChildren<T>>::clear_prefix((id,), u32::MAX, None);456 let _ = <Owned<T>>::clear_prefix((id,), u32::MAX, None);457 <TokensMinted<T>>::remove(id);458 <TokensBurnt<T>>::remove(id);459 let _ = <Allowance<T>>::clear_prefix((id,), u32::MAX, None);460 let _ = <AccountBalance<T>>::clear_prefix((id,), u32::MAX, None);461 let _ = <CollectionAllowance<T>>::clear_prefix((id,), u32::MAX, None);462 Ok(())463 }464465 /// Burn NFT token466 ///467 /// `burn` removes `token` from the `collection`, from it's owner and from the parent token468 /// if the token is nested.469 /// Only the owner can `burn` the token. The `token` shouldn't have any nested tokens.470 /// Also removes all corresponding properties and auxiliary properties.471 ///472 /// - `token`: Token that should be burned473 /// - `collection`: Collection that contains the token474 pub fn burn(475 collection: &NonfungibleHandle<T>,476 sender: &T::CrossAccountId,477 token: TokenId,478 ) -> DispatchResult {479 let token_data =480 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;481 ensure!(&token_data.owner == sender, <CommonError<T>>::NoPermission);482483 if collection.permissions.access() == AccessMode::AllowList {484 collection.check_allowlist(sender)?;485 }486487 if Self::token_has_children(collection.id, token) {488 return Err(<Error<T>>::CantBurnNftWithChildren.into());489 }490491 let burnt = <TokensBurnt<T>>::get(collection.id)492 .checked_add(1)493 .ok_or(ArithmeticError::Overflow)?;494495 let balance = <AccountBalance<T>>::get((collection.id, token_data.owner.clone()))496 .checked_sub(1)497 .ok_or(ArithmeticError::Overflow)?;498499 // =========500501 if balance == 0 {502 <AccountBalance<T>>::remove((collection.id, token_data.owner.clone()));503 } else {504 <AccountBalance<T>>::insert((collection.id, token_data.owner.clone()), balance);505 }506507 <PalletStructure<T>>::unnest_if_nested(&token_data.owner, collection.id, token);508509 <Owned<T>>::remove((collection.id, &token_data.owner, token));510 <TokensBurnt<T>>::insert(collection.id, burnt);511 <TokenData<T>>::remove((collection.id, token));512 <TokenProperties<T>>::remove((collection.id, token));513 let _ = <TokenAuxProperties<T>>::clear_prefix((collection.id, token), u32::MAX, None);514 let old_spender = <Allowance<T>>::take((collection.id, token));515516 if let Some(old_spender) = old_spender {517 <PalletCommon<T>>::deposit_event(CommonEvent::Approved(518 collection.id,519 token,520 token_data.owner.clone(),521 old_spender,522 0,523 ));524 }525526 <PalletEvm<T>>::deposit_log(527 ERC721Events::Transfer {528 from: *token_data.owner.as_eth(),529 to: H160::default(),530 token_id: token.into(),531 }532 .to_log(collection_id_to_address(collection.id)),533 );534 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(535 collection.id,536 token,537 token_data.owner,538 1,539 ));540 Ok(())541 }542543 /// Same as [`burn`] but burns all the tokens that are nested in the token first544 ///545 /// - `self_budget`: Limit for searching children in depth.546 /// - `breadth_budget`: Limit of breadth of searching children.547 ///548 /// [`burn`]: struct.Pallet.html#method.burn549 #[transactional]550 pub fn burn_recursively(551 collection: &NonfungibleHandle<T>,552 sender: &T::CrossAccountId,553 token: TokenId,554 self_budget: &dyn Budget,555 breadth_budget: &dyn Budget,556 ) -> DispatchResultWithPostInfo {557 ensure!(self_budget.consume(), <StructureError<T>>::DepthLimit,);558559 let current_token_account =560 T::CrossTokenAddressMapping::token_to_address(collection.id, token);561562 let mut weight = Weight::zero();563564 // This method is transactional, if user in fact doesn't have permissions to remove token -565 // tokens removed here will be restored after rejected transaction566 for ((collection, token), _) in <TokenChildren<T>>::iter_prefix((collection.id, token)) {567 ensure!(breadth_budget.consume(), <StructureError<T>>::BreadthLimit,);568 let PostDispatchInfo { actual_weight, .. } =569 <PalletStructure<T>>::burn_item_recursively(570 current_token_account.clone(),571 collection,572 token,573 self_budget,574 breadth_budget,575 )?;576 if let Some(actual_weight) = actual_weight {577 weight = weight.saturating_add(actual_weight);578 }579 }580581 Self::burn(collection, sender, token)?;582 DispatchResultWithPostInfo::Ok(PostDispatchInfo {583 actual_weight: Some(weight + <SelfWeightOf<T>>::burn_item()),584 pays_fee: Pays::Yes,585 })586 }587588 /// A batch operation to add, edit or remove properties for a token.589 ///590 /// - `nesting_budget`: Limit for searching parents in-depth to check ownership.591 /// - `is_token_create`: Indicates that method is called during token initialization.592 /// Allows to bypass ownership check.593 ///594 /// All affected properties should have `mutable` permission595 /// to be **deleted** or to be **set more than once**,596 /// and the sender should have permission to edit those properties.597 ///598 /// This function fires an event for each property change.599 /// In case of an error, all the changes (including the events) will be reverted600 /// since the function is transactional.601 #[transactional]602 fn modify_token_properties(603 collection: &NonfungibleHandle<T>,604 sender: &T::CrossAccountId,605 token_id: TokenId,606 properties_updates: impl Iterator<Item = (PropertyKey, Option<PropertyValue>)>,607 is_token_create: bool,608 nesting_budget: &dyn Budget,609 ) -> DispatchResult {610 let is_token_owner = || {611 let is_owned = <PalletStructure<T>>::check_indirectly_owned(612 sender.clone(),613 collection.id,614 token_id,615 None,616 nesting_budget,617 )?;618619 Ok(is_owned)620 };621622 let stored_properties = <TokenProperties<T>>::get((collection.id, token_id));623624 <PalletCommon<T>>::modify_token_properties(625 collection,626 sender,627 token_id,628 properties_updates,629 is_token_create,630 stored_properties,631 is_token_owner,632 |properties| <TokenProperties<T>>::set((collection.id, token_id), properties),633 erc::ERC721TokenEvent::TokenChanged {634 token_id: token_id.into(),635 }636 .to_log(T::ContractAddress::get()),637 )638 }639640 /// Batch operation to add or edit properties for the token641 ///642 /// Same as [`modify_token_properties`] but doesn't allow to remove properties643 ///644 /// [`modify_token_properties`]: struct.Pallet.html#method.modify_token_properties645 pub fn set_token_properties(646 collection: &NonfungibleHandle<T>,647 sender: &T::CrossAccountId,648 token_id: TokenId,649 properties: impl Iterator<Item = Property>,650 is_token_create: bool,651 nesting_budget: &dyn Budget,652 ) -> DispatchResult {653 Self::modify_token_properties(654 collection,655 sender,656 token_id,657 properties.map(|p| (p.key, Some(p.value))),658 is_token_create,659 nesting_budget,660 )661 }662663 /// Add or edit single property for the token664 ///665 /// Calls [`set_token_properties`] internally666 ///667 /// [`set_token_properties`]: struct.Pallet.html#method.set_token_properties668 pub fn set_token_property(669 collection: &NonfungibleHandle<T>,670 sender: &T::CrossAccountId,671 token_id: TokenId,672 property: Property,673 nesting_budget: &dyn Budget,674 ) -> DispatchResult {675 let is_token_create = false;676677 Self::set_token_properties(678 collection,679 sender,680 token_id,681 [property].into_iter(),682 is_token_create,683 nesting_budget,684 )685 }686687 /// Batch operation to remove properties from the token688 ///689 /// Same as [`modify_token_properties`] but doesn't allow to add or edit properties690 ///691 /// [`modify_token_properties`]: struct.Pallet.html#method.modify_token_properties692 pub fn delete_token_properties(693 collection: &NonfungibleHandle<T>,694 sender: &T::CrossAccountId,695 token_id: TokenId,696 property_keys: impl Iterator<Item = PropertyKey>,697 nesting_budget: &dyn Budget,698 ) -> DispatchResult {699 let is_token_create = false;700701 Self::modify_token_properties(702 collection,703 sender,704 token_id,705 property_keys.into_iter().map(|key| (key, None)),706 is_token_create,707 nesting_budget,708 )709 }710711 /// Remove single property from the token712 ///713 /// Calls [`delete_token_properties`] internally714 ///715 /// [`delete_token_properties`]: struct.Pallet.html#method.delete_token_properties716 pub fn delete_token_property(717 collection: &NonfungibleHandle<T>,718 sender: &T::CrossAccountId,719 token_id: TokenId,720 property_key: PropertyKey,721 nesting_budget: &dyn Budget,722 ) -> DispatchResult {723 Self::delete_token_properties(724 collection,725 sender,726 token_id,727 [property_key].into_iter(),728 nesting_budget,729 )730 }731732 /// Add or edit properties for the collection733 pub fn set_collection_properties(734 collection: &NonfungibleHandle<T>,735 sender: &T::CrossAccountId,736 properties: Vec<Property>,737 ) -> DispatchResult {738 <PalletCommon<T>>::set_collection_properties(collection, sender, properties.into_iter())739 }740741 /// Remove properties from the collection742 pub fn delete_collection_properties(743 collection: &CollectionHandle<T>,744 sender: &T::CrossAccountId,745 property_keys: Vec<PropertyKey>,746 ) -> DispatchResult {747 <PalletCommon<T>>::delete_collection_properties(748 collection,749 sender,750 property_keys.into_iter(),751 )752 }753754 /// Set property permissions for the token.755 ///756 /// Sender should be the owner or admin of token's collection.757 pub fn set_token_property_permissions(758 collection: &CollectionHandle<T>,759 sender: &T::CrossAccountId,760 property_permissions: Vec<PropertyKeyPermission>,761 ) -> DispatchResult {762 <PalletCommon<T>>::set_token_property_permissions(collection, sender, property_permissions)763 }764765 /// Set property permissions for the token with scope.766 ///767 /// Sender should be the owner or admin of token's collection.768 pub fn set_scoped_token_property_permissions(769 collection: &CollectionHandle<T>,770 sender: &T::CrossAccountId,771 scope: PropertyScope,772 property_permissions: Vec<PropertyKeyPermission>,773 ) -> DispatchResult {774 <PalletCommon<T>>::set_scoped_token_property_permissions(775 collection,776 sender,777 scope,778 property_permissions,779 )780 }781782 pub fn token_property_permission(collection_id: CollectionId) -> PropertiesPermissionMap {783 <PalletCommon<T>>::property_permissions(collection_id)784 }785786 pub fn check_token_immediate_ownership(787 collection: &NonfungibleHandle<T>,788 token: TokenId,789 possible_owner: &T::CrossAccountId,790 ) -> DispatchResult {791 let token_data =792 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;793 ensure!(794 &token_data.owner == possible_owner,795 <CommonError<T>>::NoPermission796 );797 Ok(())798 }799800 /// Transfer NFT token from one account to another.801 ///802 /// `from` account stops being the owner and `to` account becomes the owner of the token.803 /// If `to` is token than `to` becomes owner of the token and the token become nested.804 /// Unnests token from previous parent if it was nested before.805 /// Removes allowance for the token if there was any.806 /// Throws if transfers aren't allowed for collection or if receiver reached token ownership limit.807 ///808 /// - `nesting_budget`: Limit for token nesting depth809 pub fn transfer(810 collection: &NonfungibleHandle<T>,811 from: &T::CrossAccountId,812 to: &T::CrossAccountId,813 token: TokenId,814 nesting_budget: &dyn Budget,815 ) -> DispatchResultWithPostInfo {816 ensure!(817 collection.limits.transfers_enabled(),818 <CommonError<T>>::TransferNotAllowed819 );820821 let mut actual_weight = <SelfWeightOf<T>>::transfer_raw();822 let token_data =823 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;824 ensure!(&token_data.owner == from, <CommonError<T>>::NoPermission);825826 if collection.permissions.access() == AccessMode::AllowList {827 collection.check_allowlist(from)?;828 collection.check_allowlist(to)?;829 actual_weight += <PalletCommonWeightOf<T>>::check_accesslist() * 2;830 }831 <PalletCommon<T>>::ensure_correct_receiver(to)?;832833 let balance_from = <AccountBalance<T>>::get((collection.id, from))834 .checked_sub(1)835 .ok_or(<CommonError<T>>::TokenValueTooLow)?;836 let balance_to = if from != to {837 let balance_to = <AccountBalance<T>>::get((collection.id, to))838 .checked_add(1)839 .ok_or(ArithmeticError::Overflow)?;840841 ensure!(842 balance_to < collection.limits.account_token_ownership_limit(),843 <CommonError<T>>::AccountTokenLimitExceeded,844 );845846 Some(balance_to)847 } else {848 None849 };850851 <PalletStructure<T>>::nest_if_sent_to_token(852 from.clone(),853 to,854 collection.id,855 token,856 nesting_budget,857 )?;858859 // =========860861 <PalletStructure<T>>::unnest_if_nested(&token_data.owner, collection.id, token);862863 <TokenData<T>>::insert(864 (collection.id, token),865 ItemData {866 owner: to.clone(),867 ..token_data868 },869 );870871 if let Some(balance_to) = balance_to {872 // from != to873 if balance_from == 0 {874 <AccountBalance<T>>::remove((collection.id, from));875 } else {876 <AccountBalance<T>>::insert((collection.id, from), balance_from);877 }878 <AccountBalance<T>>::insert((collection.id, to), balance_to);879 <Owned<T>>::remove((collection.id, from, token));880 <Owned<T>>::insert((collection.id, to, token), true);881 }882 Self::set_allowance_unchecked(collection, from, token, None, true);883884 <PalletEvm<T>>::deposit_log(885 ERC721Events::Transfer {886 from: *from.as_eth(),887 to: *to.as_eth(),888 token_id: token.into(),889 }890 .to_log(collection_id_to_address(collection.id)),891 );892 <PalletCommon<T>>::deposit_event(CommonEvent::Transfer(893 collection.id,894 token,895 from.clone(),896 to.clone(),897 1,898 ));899900 Ok(PostDispatchInfo {901 actual_weight: Some(actual_weight),902 pays_fee: Pays::Yes,903 })904 }905906 /// Batch operation to mint multiple NFT tokens.907 ///908 /// The sender should be the owner/admin of the collection or collection should be configured909 /// to allow public minting.910 /// Throws if amount of tokens reached it's limit for the collection or if caller reached911 /// token ownership limit.912 ///913 /// - `data`: Contains list of token properties and users who will become the owners of the914 /// corresponging tokens.915 /// - `nesting_budget`: Limit for token nesting depth916 pub fn create_multiple_items(917 collection: &NonfungibleHandle<T>,918 sender: &T::CrossAccountId,919 data: Vec<CreateItemData<T>>,920 nesting_budget: &dyn Budget,921 ) -> DispatchResult {922 if !collection.is_owner_or_admin(sender) {923 ensure!(924 collection.permissions.mint_mode(),925 <CommonError<T>>::PublicMintingNotAllowed926 );927 collection.check_allowlist(sender)?;928929 for item in data.iter() {930 collection.check_allowlist(&item.owner)?;931 }932 }933934 for data in data.iter() {935 <PalletCommon<T>>::ensure_correct_receiver(&data.owner)?;936 }937938 let first_token = <TokensMinted<T>>::get(collection.id);939 let tokens_minted = first_token940 .checked_add(data.len() as u32)941 .ok_or(ArithmeticError::Overflow)?;942 ensure!(943 tokens_minted <= collection.limits.token_limit(),944 <CommonError<T>>::CollectionTokenLimitExceeded945 );946947 let mut balances = BTreeMap::new();948 for data in &data {949 let balance = balances950 .entry(&data.owner)951 .or_insert_with(|| <AccountBalance<T>>::get((collection.id, &data.owner)));952 *balance = balance.checked_add(1).ok_or(ArithmeticError::Overflow)?;953954 ensure!(955 *balance <= collection.limits.account_token_ownership_limit(),956 <CommonError<T>>::AccountTokenLimitExceeded,957 );958 }959960 for (i, data) in data.iter().enumerate() {961 let token = TokenId(first_token + i as u32 + 1);962963 <PalletStructure<T>>::check_nesting(964 sender.clone(),965 &data.owner,966 collection.id,967 token,968 nesting_budget,969 )?;970 }971972 // =========973974 with_transaction(|| {975 for (i, data) in data.iter().enumerate() {976 let token = first_token + i as u32 + 1;977978 <TokenData<T>>::insert(979 (collection.id, token),980 ItemData {981 // const_data: data.const_data.clone(),982 owner: data.owner.clone(),983 },984 );985986 <PalletStructure<T>>::nest_if_sent_to_token_unchecked(987 &data.owner,988 collection.id,989 TokenId(token),990 );991992 if let Err(e) = Self::set_token_properties(993 collection,994 sender,995 TokenId(token),996 data.properties.clone().into_iter(),997 true,998 nesting_budget,999 ) {1000 return TransactionOutcome::Rollback(Err(e));1001 }1002 }1003 TransactionOutcome::Commit(Ok(()))1004 })?;10051006 <TokensMinted<T>>::insert(collection.id, tokens_minted);1007 for (account, balance) in balances {1008 <AccountBalance<T>>::insert((collection.id, account), balance);1009 }1010 for (i, data) in data.into_iter().enumerate() {1011 let token = first_token + i as u32 + 1;1012 <Owned<T>>::insert((collection.id, &data.owner, token), true);10131014 <PalletEvm<T>>::deposit_log(1015 ERC721Events::Transfer {1016 from: H160::default(),1017 to: *data.owner.as_eth(),1018 token_id: token.into(),1019 }1020 .to_log(collection_id_to_address(collection.id)),1021 );1022 <PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(1023 collection.id,1024 TokenId(token),1025 data.owner.clone(),1026 1,1027 ));1028 }1029 Ok(())1030 }10311032 pub fn set_allowance_unchecked(1033 collection: &NonfungibleHandle<T>,1034 sender: &T::CrossAccountId,1035 token: TokenId,1036 spender: Option<&T::CrossAccountId>,1037 assume_implicit_eth: bool,1038 ) {1039 if let Some(spender) = spender {1040 let old_spender = <Allowance<T>>::get((collection.id, token));1041 <Allowance<T>>::insert((collection.id, token), spender);1042 // In ERC721 there is only one possible approved user of token, so we set1043 // approved user to spender1044 <PalletEvm<T>>::deposit_log(1045 ERC721Events::Approval {1046 owner: *sender.as_eth(),1047 approved: *spender.as_eth(),1048 token_id: token.into(),1049 }1050 .to_log(collection_id_to_address(collection.id)),1051 );1052 // In Unique chain, any token can have any amount of approved users, so we need to1053 // set allowance of old owner to 0, and allowance of new owner to 11054 if old_spender.as_ref() != Some(spender) {1055 if let Some(old_owner) = old_spender {1056 <PalletCommon<T>>::deposit_event(CommonEvent::Approved(1057 collection.id,1058 token,1059 sender.clone(),1060 old_owner,1061 0,1062 ));1063 }1064 <PalletCommon<T>>::deposit_event(CommonEvent::Approved(1065 collection.id,1066 token,1067 sender.clone(),1068 spender.clone(),1069 1,1070 ));1071 }1072 } else {1073 let old_spender = <Allowance<T>>::take((collection.id, token));1074 if !assume_implicit_eth {1075 // In ERC721 there is only one possible approved user of token, so we set1076 // approved user to zero address1077 <PalletEvm<T>>::deposit_log(1078 ERC721Events::Approval {1079 owner: *sender.as_eth(),1080 approved: H160::default(),1081 token_id: token.into(),1082 }1083 .to_log(collection_id_to_address(collection.id)),1084 );1085 }1086 // In Unique chain, any token can have any amount of approved users, so we need to1087 // set allowance of old owner to 01088 if let Some(old_spender) = old_spender {1089 <PalletCommon<T>>::deposit_event(CommonEvent::Approved(1090 collection.id,1091 token,1092 sender.clone(),1093 old_spender,1094 0,1095 ));1096 }1097 }1098 }10991100 pub fn get_allowance(1101 collection: &NonfungibleHandle<T>,1102 token_id: TokenId,1103 ) -> Result<Option<T::CrossAccountId>, DispatchError> {1104 ensure!(1105 <TokenData<T>>::get((collection.id, token_id)).is_some(),1106 <CommonError<T>>::TokenNotFound1107 );1108 Ok(<Allowance<T>>::get((collection.id, token_id)))1109 }11101111 /// Set allowance for the spender to `transfer` or `burn` sender's token.1112 ///1113 /// - `token`: Token the spender is allowed to `transfer` or `burn`.1114 pub fn set_allowance(1115 collection: &NonfungibleHandle<T>,1116 sender: &T::CrossAccountId,1117 token: TokenId,1118 spender: Option<&T::CrossAccountId>,1119 ) -> DispatchResult {1120 if collection.permissions.access() == AccessMode::AllowList {1121 collection.check_allowlist(sender)?;1122 if let Some(spender) = spender {1123 collection.check_allowlist(spender)?;1124 }1125 }11261127 if let Some(spender) = spender {1128 <PalletCommon<T>>::ensure_correct_receiver(spender)?;1129 }11301131 let token_data =1132 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;1133 if &token_data.owner != sender {1134 ensure!(1135 collection.ignores_owned_amount(sender),1136 <CommonError<T>>::CantApproveMoreThanOwned1137 );1138 }11391140 // =========11411142 Self::set_allowance_unchecked(collection, sender, token, spender, false);1143 Ok(())1144 }11451146 /// Set allowance for the spender to `transfer` or `burn` sender's token from eth mirror.1147 ///1148 /// - `from`: Address of sender's eth mirror.1149 /// - `to`: Adress of spender.1150 /// - `token`: Token the spender is allowed to `transfer` or `burn`.1151 pub fn set_allowance_from(1152 collection: &NonfungibleHandle<T>,1153 sender: &T::CrossAccountId,1154 from: &T::CrossAccountId,1155 token: TokenId,1156 to: Option<&T::CrossAccountId>,1157 ) -> DispatchResult {1158 if collection.permissions.access() == AccessMode::AllowList {1159 collection.check_allowlist(sender)?;1160 collection.check_allowlist(from)?;1161 if let Some(to) = to {1162 collection.check_allowlist(to)?;1163 }1164 }11651166 if let Some(to) = to {1167 <PalletCommon<T>>::ensure_correct_receiver(to)?;1168 }11691170 ensure!(1171 sender.conv_eq(from),1172 <CommonError<T>>::AddressIsNotEthMirror1173 );11741175 let token_data =1176 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;1177 if token_data.owner != *from {1178 ensure!(1179 collection.limits.owner_can_transfer()1180 && (collection.is_owner_or_admin(sender) || collection.is_owner_or_admin(from)),1181 <CommonError<T>>::CantApproveMoreThanOwned1182 );1183 }11841185 // =========11861187 Self::set_allowance_unchecked(collection, from, token, to, false);1188 Ok(())1189 }11901191 /// Checks allowance for the spender to use the token.1192 fn check_allowed(1193 collection: &NonfungibleHandle<T>,1194 spender: &T::CrossAccountId,1195 from: &T::CrossAccountId,1196 token: TokenId,1197 nesting_budget: &dyn Budget,1198 ) -> DispatchResult {1199 if spender.conv_eq(from) {1200 return Ok(());1201 }1202 if collection.permissions.access() == AccessMode::AllowList {1203 // `from`, `to` checked in [`transfer`]1204 collection.check_allowlist(spender)?;1205 }12061207 if collection.ignores_token_restrictions(spender) {1208 return Ok(());1209 }12101211 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {1212 ensure!(1213 <PalletStructure<T>>::check_indirectly_owned(1214 spender.clone(),1215 source.0,1216 source.1,1217 None,1218 nesting_budget1219 )?,1220 <CommonError<T>>::ApprovedValueTooLow,1221 );1222 return Ok(());1223 }1224 if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {1225 return Ok(());1226 }1227 if <CollectionAllowance<T>>::get((collection.id, from, spender)) {1228 return Ok(());1229 }12301231 Err(<CommonError<T>>::ApprovedValueTooLow.into())1232 }12331234 /// Transfer NFT token from one account to another.1235 ///1236 /// Same as the [`transfer`] but spender doesn't needs to be the owner of the token.1237 /// The owner should set allowance for the spender to transfer token.1238 ///1239 /// [`transfer`]: struct.Pallet.html#method.transfer1240 pub fn transfer_from(1241 collection: &NonfungibleHandle<T>,1242 spender: &T::CrossAccountId,1243 from: &T::CrossAccountId,1244 to: &T::CrossAccountId,1245 token: TokenId,1246 nesting_budget: &dyn Budget,1247 ) -> DispatchResultWithPostInfo {1248 Self::check_allowed(collection, spender, from, token, nesting_budget)?;12491250 // =========12511252 // Allowance is reset in [`transfer`]1253 let mut result = Self::transfer(collection, from, to, token, nesting_budget);1254 add_weight_to_post_info(&mut result, <SelfWeightOf<T>>::check_allowed_raw());1255 result1256 }12571258 /// Burn NFT token for `from` account.1259 ///1260 /// Same as the [`burn`] but spender doesn't need to be an owner of the token. The owner should1261 /// set allowance for the spender to burn token.1262 ///1263 /// [`burn`]: struct.Pallet.html#method.burn1264 pub fn burn_from(1265 collection: &NonfungibleHandle<T>,1266 spender: &T::CrossAccountId,1267 from: &T::CrossAccountId,1268 token: TokenId,1269 nesting_budget: &dyn Budget,1270 ) -> DispatchResult {1271 Self::check_allowed(collection, spender, from, token, nesting_budget)?;12721273 // =========12741275 Self::burn(collection, from, token)1276 }12771278 /// Check that `from` token could be nested in `under` token.1279 ///1280 pub fn check_nesting(1281 handle: &NonfungibleHandle<T>,1282 sender: T::CrossAccountId,1283 from: (CollectionId, TokenId),1284 under: TokenId,1285 nesting_budget: &dyn Budget,1286 ) -> DispatchResult {1287 let nesting = handle.permissions.nesting();12881289 #[cfg(not(feature = "runtime-benchmarks"))]1290 let permissive = false;1291 #[cfg(feature = "runtime-benchmarks")]1292 let permissive = nesting.permissive;12931294 if permissive {1295 ensure!(1296 <TokenData<T>>::contains_key((handle.id, under)),1297 <CommonError<T>>::TokenNotFound1298 );1299 } else if nesting.token_owner1300 && <PalletStructure<T>>::check_indirectly_owned(1301 sender.clone(),1302 handle.id,1303 under,1304 Some(from),1305 nesting_budget,1306 )? {1307 // Pass, token existence and ouroboros checks are done in `check_indirectly_owned`1308 } else if nesting.collection_admin && handle.is_owner_or_admin(&sender) {1309 // token existence and ouroboros checks are done in `get_checked_topmost_owner`1310 let _ = <PalletStructure<T>>::get_checked_topmost_owner(1311 handle.id,1312 under,1313 Some(from),1314 nesting_budget,1315 )?1316 .ok_or(<CommonError<T>>::TokenNotFound)?;1317 } else {1318 fail!(<CommonError<T>>::UserIsNotAllowedToNest);1319 }13201321 if let Some(whitelist) = &nesting.restricted {1322 ensure!(1323 whitelist.contains(&from.0),1324 <CommonError<T>>::SourceCollectionIsNotAllowedToNest1325 );1326 }1327 Ok(())1328 }13291330 fn nest(under: (CollectionId, TokenId), to_nest: (CollectionId, TokenId)) {1331 if to_nest.0 != pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {1332 <TokenChildren<T>>::insert((under.0, under.1, to_nest), true);1333 }1334 }13351336 fn unnest(under: (CollectionId, TokenId), to_unnest: (CollectionId, TokenId)) {1337 if to_unnest.0 != pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {1338 <TokenChildren<T>>::remove((under.0, under.1, to_unnest));1339 }1340 }13411342 fn collection_has_tokens(collection_id: CollectionId) -> bool {1343 <TokenData<T>>::iter_prefix((collection_id,))1344 .next()1345 .is_some()1346 }13471348 fn token_has_children(collection_id: CollectionId, token_id: TokenId) -> bool {1349 <TokenChildren<T>>::iter_prefix((collection_id, token_id))1350 .next()1351 .is_some()1352 }13531354 pub fn token_children_ids(collection_id: CollectionId, token_id: TokenId) -> Vec<TokenChild> {1355 <TokenChildren<T>>::iter_prefix((collection_id, token_id))1356 .map(|((child_collection_id, child_id), _)| TokenChild {1357 collection: child_collection_id,1358 token: child_id,1359 })1360 .collect()1361 }13621363 /// Mint single NFT token.1364 ///1365 /// Delegated to [`create_multiple_items`]1366 ///1367 /// [`create_multiple_items`]: struct.Pallet.html#method.create_multiple_items1368 pub fn create_item(1369 collection: &NonfungibleHandle<T>,1370 sender: &T::CrossAccountId,1371 data: CreateItemData<T>,1372 nesting_budget: &dyn Budget,1373 ) -> DispatchResult {1374 Self::create_multiple_items(collection, sender, vec![data], nesting_budget)1375 }13761377 /// Sets or unsets the approval of a given operator.1378 ///1379 /// The `operator` is allowed to transfer all token pieces of the `owner` on their behalf.1380 /// - `owner`: Token owner1381 /// - `operator`: Operator1382 /// - `approve`: Should operator status be granted or revoked?1383 pub fn set_allowance_for_all(1384 collection: &NonfungibleHandle<T>,1385 owner: &T::CrossAccountId,1386 operator: &T::CrossAccountId,1387 approve: bool,1388 ) -> DispatchResult {1389 <PalletCommon<T>>::set_allowance_for_all(1390 collection,1391 owner,1392 operator,1393 approve,1394 || <CollectionAllowance<T>>::insert((collection.id, owner, operator), approve),1395 ERC721Events::ApprovalForAll {1396 owner: *owner.as_eth(),1397 operator: *operator.as_eth(),1398 approved: approve,1399 }1400 .to_log(collection_id_to_address(collection.id)),1401 )1402 }14031404 /// Tells whether the given `owner` approves the `operator`.1405 pub fn allowance_for_all(1406 collection: &NonfungibleHandle<T>,1407 owner: &T::CrossAccountId,1408 operator: &T::CrossAccountId,1409 ) -> bool {1410 <CollectionAllowance<T>>::get((collection.id, owner, operator))1411 }14121413 pub fn repair_item(collection: &NonfungibleHandle<T>, token: TokenId) -> DispatchResult {1414 <TokenProperties<T>>::mutate((collection.id, token), |properties| {1415 properties.recompute_consumed_space();1416 });14171418 Ok(())1419 }1420}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.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -536,7 +536,7 @@
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
- return &self.0;
+ &self.0
}
}
@@ -816,6 +816,11 @@
Self(Default::default())
}
}
+impl Default for OwnerRestrictedSet {
+ fn default() -> Self {
+ Self::new()
+ }
+}
impl core::ops::Deref for OwnerRestrictedSet {
type Target = OwnerRestrictedSetInner;
fn deref(&self) -> &Self::Target {
@@ -1098,9 +1103,9 @@
pub value: PropertyValue,
}
-impl Into<(PropertyKey, PropertyValue)> for Property {
- fn into(self) -> (PropertyKey, PropertyValue) {
- (self.key, self.value)
+impl From<Property> for (PropertyKey, PropertyValue) {
+ fn from(value: Property) -> Self {
+ (value.key, value.value)
}
}
@@ -1116,9 +1121,9 @@
pub permission: PropertyPermission,
}
-impl Into<(PropertyKey, PropertyPermission)> for PropertyKeyPermission {
- fn into(self) -> (PropertyKey, PropertyPermission) {
- (self.key, self.permission)
+impl From<PropertyKeyPermission> for (PropertyKey, PropertyPermission) {
+ fn from(value: PropertyKeyPermission) -> Self {
+ (value.key, value.permission)
}
}
@@ -1415,7 +1420,7 @@
value: Self::Value,
) -> Result<Option<Self::Value>, PropertiesError> {
let key_size = scoped_slice_size(scope, &key);
- let value_size = slice_size(&value) as u32;
+ let value_size = slice_size(&value);
if self.consumed_space + value_size + key_size > S && !cfg!(feature = "runtime-benchmarks")
{
@@ -1425,7 +1430,7 @@
let old_value = self.map.try_scoped_set(scope, key, value)?;
if let Some(old_value) = old_value.as_ref() {
- let old_value_size = slice_size(&old_value);
+ let old_value_size = slice_size(old_value);
self.consumed_space = self.consumed_space.saturating_sub(old_value_size) + value_size;
} else {
self.consumed_space += key_size + value_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())
}
}