--- a/Cargo.lock +++ b/Cargo.lock @@ -6262,7 +6262,7 @@ [[package]] name = "pallet-common" -version = "0.1.13" +version = "0.1.14" dependencies = [ "ethereum", "evm-coder", @@ -6558,7 +6558,7 @@ [[package]] name = "pallet-fungible" -version = "0.1.10" +version = "0.1.11" dependencies = [ "evm-coder", "frame-benchmarking", @@ -6814,7 +6814,7 @@ [[package]] name = "pallet-nonfungible" -version = "0.1.13" +version = "0.1.14" dependencies = [ "evm-coder", "frame-benchmarking", --- a/pallets/app-promotion/src/lib.rs +++ b/pallets/app-promotion/src/lib.rs @@ -845,7 +845,6 @@ /// - `staker`: staker account. pub fn total_staked_by_id(staker: impl EncodeLike) -> Option> { let staked = Staked::::iter_prefix((staker,)) - .into_iter() .fold(>::default(), |acc, (_, (amount, _))| { acc + amount }); @@ -864,7 +863,6 @@ staker: impl EncodeLike, ) -> Option)>> { let mut staked = Staked::::iter_prefix((staker,)) - .into_iter() .map(|(block, (amount, _))| (block, amount)) .collect::>(); staked.sort_by_key(|(block, _)| *block); @@ -883,12 +881,6 @@ Self::total_staked_by_id(s.as_sub()) }) } - - // pub fn cross_id_locked_balance(staker: T::CrossAccountId) -> BalanceOf { - // Self::get_locked_balance(staker.as_sub()) - // .map(|l| l.amount) - // .unwrap_or_default() - // } /// Returns all relay block numbers when stake was made, /// the amount of the stake. --- a/pallets/common/CHANGELOG.md +++ b/pallets/common/CHANGELOG.md @@ -4,6 +4,12 @@ +## [0.1.14] - 2023-03-28 + +### Added + +- Added benchmark to check if user is contained in AllowList (`check_accesslist()`). + ## [0.1.13] - 2023-01-20 ### Changed --- a/pallets/common/Cargo.toml +++ b/pallets/common/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" license = "GPLv3" name = "pallet-common" -version = "0.1.13" +version = "0.1.14" [dependencies] # Note: `package = "parity-scale-codec"` must be supplied since the `Encode` macro searches for it. --- a/pallets/common/src/benchmarking.rs +++ b/pallets/common/src/benchmarking.rs @@ -22,8 +22,9 @@ use frame_benchmarking::{benchmarks, account}; use up_data_structs::{ CollectionMode, CollectionFlags, CreateCollectionData, CollectionId, Property, PropertyKey, - PropertyValue, CollectionPermissions, NestingPermissions, MAX_COLLECTION_NAME_LENGTH, - MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, MAX_PROPERTIES_PER_ITEM, + PropertyValue, CollectionPermissions, NestingPermissions, AccessMode, + MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, + MAX_PROPERTIES_PER_ITEM, }; use frame_support::{ traits::{Currency, Get}, @@ -193,4 +194,28 @@ >::set_collection_properties(&collection, &owner, props.into_iter())?; let to_delete = (0..b).map(|p| property_key(p as usize)).collect::>(); }: {>::delete_collection_properties(&collection, &owner, to_delete.into_iter())?} + + check_accesslist{ + bench_init!{ + owner: sub; collection: collection(owner); + sender: cross_from_sub(owner); + }; + + let mut collection_handle = >::try_get(collection.id)?; + >::update_permissions( + &sender, + &mut collection_handle, + CollectionPermissions { access: Some(AccessMode::AllowList), ..Default::default() } + )?; + + >::toggle_allowlist( + &collection, + &sender, + &sender, + true, + )?; + + assert_eq!(collection_handle.permissions.access(), AccessMode::AllowList); + + }: {collection_handle.check_allowlist(&sender)?;} } --- /dev/null +++ b/pallets/common/src/helpers.rs @@ -0,0 +1,30 @@ +//! # Helpers module +//! +//! The module contains helpers. +//! +use frame_support::{ + pallet_prelude::DispatchResultWithPostInfo, + weights::Weight, + dispatch::{DispatchErrorWithPostInfo, PostDispatchInfo}, +}; + +/// Add weight for a `DispatchResultWithPostInfo` +/// +/// - `target`: DispatchResultWithPostInfo to which weight will be added +/// - `additional_weight`: Weight to be added +pub fn add_weight_to_post_info(target: &mut DispatchResultWithPostInfo, additional_weight: Weight) { + match target { + Ok(PostDispatchInfo { + actual_weight: Some(weight), + .. + }) + | Err(DispatchErrorWithPostInfo { + post_info: PostDispatchInfo { + actual_weight: Some(weight), + .. + }, + .. + }) => *weight += additional_weight, + _ => {} + } +} --- a/pallets/common/src/lib.rs +++ b/pallets/common/src/lib.rs @@ -92,9 +92,9 @@ pub mod dispatch; pub mod erc; pub mod eth; +pub mod helpers; #[allow(missing_docs)] pub mod weights; - /// Weight info. pub type SelfWeightOf = ::WeightInfo; --- a/pallets/common/src/weights.rs +++ b/pallets/common/src/weights.rs @@ -36,6 +36,7 @@ pub trait WeightInfo { fn set_collection_properties(b: u32, ) -> Weight; fn delete_collection_properties(b: u32, ) -> Weight; + fn check_accesslist() -> Weight; } /// Weights for pallet_common using the Substrate node and recommended hardware. @@ -69,6 +70,16 @@ .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } + /// Storage: Common Allowlist (r:1 w:0) + /// Proof: Common Allowlist (max_values: None, max_size: Some(70), added: 2545, mode: MaxEncodedLen) + fn check_accesslist() -> Weight { + // Proof Size summary in bytes: + // Measured: `340` + // Estimated: `2545` + // Minimum execution time: 2_887_000 picoseconds. + Weight::from_parts(3_072_000, 2545) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } } // For backwards compatibility and tests @@ -101,5 +112,15 @@ .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } + /// Storage: Common Allowlist (r:1 w:0) + /// Proof: Common Allowlist (max_values: None, max_size: Some(70), added: 2545, mode: MaxEncodedLen) + fn check_accesslist() -> Weight { + // Proof Size summary in bytes: + // Measured: `340` + // Estimated: `2545` + // Minimum execution time: 2_887_000 picoseconds. + Weight::from_parts(3_072_000, 2545) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } } --- a/pallets/foreign-assets/src/impl_fungibles.rs +++ b/pallets/foreign-assets/src/impl_fungibles.rs @@ -452,7 +452,8 @@ &T::CrossAccountId::from_sub(dest.clone()), amount.into(), &Value::new(0), - )?; + ) + .map_err(|e| e.error)?; Ok(amount) } --- a/pallets/fungible/CHANGELOG.md +++ b/pallets/fungible/CHANGELOG.md @@ -4,6 +4,12 @@ +## [0.1.11] - 2023-03-28 + +### Fixed + +- The weight of `transfer` and `transfer_from`. + ## [0.1.10] - 2023-02-01 ### Added --- a/pallets/fungible/Cargo.toml +++ b/pallets/fungible/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" license = "GPLv3" name = "pallet-fungible" -version = "0.1.10" +version = "0.1.11" [dependencies] # Note: `package = "parity-scale-codec"` must be supplied since the `Encode` macro searches for it. --- a/pallets/fungible/src/benchmarking.rs +++ b/pallets/fungible/src/benchmarking.rs @@ -66,7 +66,7 @@ >::create_item(&collection, &owner, (burner.clone(), 200), &Unlimited)?; }: {>::burn(&collection, &burner, 100)?} - transfer { + transfer_raw { bench_init!{ owner: sub; collection: collection(owner); owner: cross_from_sub; sender: cross_sub; to: cross_sub; @@ -92,14 +92,22 @@ >::create_item(&collection, &owner, (owner_eth.clone(), 200), &Unlimited)?; }: {>::set_allowance_from(&collection, &sender, &owner_eth, &spender, 100)?} - transfer_from { + check_allowed_raw { bench_init!{ owner: sub; collection: collection(owner); - owner: cross_from_sub; sender: cross_sub; spender: cross_sub; receiver: cross_sub; + owner: cross_from_sub; sender: cross_sub; spender: cross_sub; }; >::create_item(&collection, &owner, (sender.clone(), 200), &Unlimited)?; >::set_allowance(&collection, &sender, &spender, 200)?; - }: {>::transfer_from(&collection, &spender, &sender, &receiver, 100, &Unlimited)?} + }: {>::check_allowed(&collection, &spender, &sender, 200, &Unlimited)?;} + + set_allowance_unchecked_raw { + bench_init!{ + owner: sub; collection: collection(owner); + owner: cross_from_sub; sender: cross_sub; spender: cross_sub; + }; + >::create_item(&collection, &owner, (sender.clone(), 200), &Unlimited)?; + }: {>::set_allowance_unchecked(&collection, &sender, &spender, 200);} burn_from { bench_init!{ --- a/pallets/fungible/src/common.rs +++ b/pallets/fungible/src/common.rs @@ -22,7 +22,7 @@ }; use pallet_common::{ CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight, - weights::WeightInfo as _, + weights::WeightInfo as _, SelfWeightOf as PalletCommonWeightOf, }; use pallet_structure::Error as StructureError; use sp_runtime::ArithmeticError; @@ -78,7 +78,7 @@ } fn transfer() -> Weight { - >::transfer() + >::transfer_raw() + >::check_accesslist() * 2 } fn approve() -> Weight { @@ -90,7 +90,9 @@ } fn transfer_from() -> Weight { - >::transfer_from() + Self::transfer() + + >::check_allowed_raw() + + >::set_allowance_unchecked_raw() } fn burn_from() -> Weight { @@ -232,10 +234,7 @@ >::FungibleItemsHaveNoId ); - with_weight( - >::transfer(self, &from, &to, amount, nesting_budget), - >::transfer(), - ) + >::transfer(self, &from, &to, amount, nesting_budget) } fn approve( @@ -289,10 +288,7 @@ >::FungibleItemsHaveNoId ); - with_weight( - >::transfer_from(self, &sender, &from, &to, amount, nesting_budget), - >::transfer_from(), - ) + >::transfer_from(self, &sender, &from, &to, amount, nesting_budget) } fn burn_from( --- a/pallets/fungible/src/erc.rs +++ b/pallets/fungible/src/erc.rs @@ -26,6 +26,7 @@ CollectionHandle, erc::{CommonEvmHandler, PrecompileResult, CollectionCall}, eth::CrossAddress, + CommonWeightInfo as _, }; use sp_std::vec::Vec; use pallet_evm::{account::CrossAccountId, PrecompileHandle}; @@ -39,7 +40,7 @@ use crate::{ Allowance, Balance, Config, FungibleHandle, Pallet, TotalSupply, SelfWeightOf, - weights::WeightInfo, + weights::WeightInfo, common::CommonWeights, }; frontier_contract! { @@ -99,7 +100,7 @@ let balance = >::get((self.id, owner)); Ok(balance.into()) } - #[weight(>::transfer())] + #[weight(>::transfer())] fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result { let caller = T::CrossAccountId::from_eth(caller); let to = T::CrossAccountId::from_eth(to); @@ -112,7 +113,7 @@ Ok(true) } - #[weight(>::transfer_from())] + #[weight(>::transfer_from())] fn transfer_from( &mut self, caller: Caller, @@ -129,7 +130,7 @@ .weight_calls_budget(>::find_parent()); >::transfer_from(self, &caller, &from, &to, amount, &budget) - .map_err(dispatch_to_evm::)?; + .map_err(|e| dispatch_to_evm::(e.error))?; Ok(true) } #[weight(>::approve())] @@ -201,7 +202,7 @@ let budget = self .recorder .weight_calls_budget(>::find_parent()); - >::create_item(&self, &caller, (to, amount), &budget) + >::create_item(self, &caller, (to, amount), &budget) .map_err(dispatch_to_evm::)?; Ok(true) } @@ -289,7 +290,7 @@ Ok(true) } - #[weight(>::transfer())] + #[weight(>::transfer())] fn transfer_cross(&mut self, caller: Caller, to: CrossAddress, amount: U256) -> Result { let caller = T::CrossAccountId::from_eth(caller); let to = to.into_sub_cross_account::()?; @@ -302,7 +303,7 @@ Ok(true) } - #[weight(>::transfer_from())] + #[weight(>::transfer_from())] fn transfer_from_cross( &mut self, caller: Caller, @@ -319,7 +320,7 @@ .weight_calls_budget(>::find_parent()); >::transfer_from(self, &caller, &from, &to, amount, &budget) - .map_err(dispatch_to_evm::)?; + .map_err(|e| dispatch_to_evm::(e.error))?; Ok(true) } --- a/pallets/fungible/src/lib.rs +++ b/pallets/fungible/src/lib.rs @@ -80,7 +80,11 @@ use core::ops::Deref; use evm_coder::ToLog; -use frame_support::ensure; +use frame_support::{ + ensure, + pallet_prelude::{DispatchResultWithPostInfo, Pays}, + dispatch::PostDispatchInfo, +}; use pallet_evm::account::CrossAccountId; use up_data_structs::{ AccessMode, CollectionId, CollectionFlags, TokenId, CreateCollectionData, @@ -88,7 +92,8 @@ }; use pallet_common::{ Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, - eth::collection_id_to_address, + eth::collection_id_to_address, SelfWeightOf as PalletCommonWeightOf, + weights::WeightInfo as CommonWeightInfo, helpers::add_weight_to_post_info, }; use pallet_evm::Pallet as PalletEvm; use pallet_structure::Pallet as PalletStructure; @@ -96,7 +101,7 @@ use sp_core::H160; use sp_runtime::{ArithmeticError, DispatchError, DispatchResult}; use sp_std::{collections::btree_map::BTreeMap, vec::Vec}; - +use weights::WeightInfo; pub use pallet::*; use crate::erc::ERC20Events; @@ -389,18 +394,20 @@ to: &T::CrossAccountId, amount: u128, nesting_budget: &dyn Budget, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { ensure!( collection.limits.transfers_enabled(), >::TransferNotAllowed, ); + let mut actual_weight = >::transfer_raw(); + if collection.permissions.access() == AccessMode::AllowList { collection.check_allowlist(from)?; collection.check_allowlist(to)?; + actual_weight += >::check_accesslist() * 2; } >::ensure_correct_receiver(to)?; - let balance_from = >::get((collection.id, from)) .checked_sub(amount) .ok_or(>::TokenValueTooLow)?; @@ -451,7 +458,11 @@ to.clone(), amount, )); - Ok(()) + + Ok(PostDispatchInfo { + actual_weight: Some(actual_weight), + pays_fee: Pays::Yes, + }) } /// Minting tokens for multiple IDs. @@ -464,8 +475,8 @@ nesting_budget: &dyn Budget, ) -> DispatchResult { let total_supply = data - .iter() - .map(|(_, v)| *v) + .values() + .copied() .try_fold(>::get(collection.id), |acc, v| { acc.checked_add(v) }) @@ -718,7 +729,6 @@ /// Same as the [`transfer`][`Pallet::transfer`] but spender doesn't needs to be an owner of the token pieces. /// The owner should set allowance for the spender to transfer pieces. /// See [`set_allowance`][`Pallet::set_allowance`] for more details. - pub fn transfer_from( collection: &FungibleHandle, spender: &T::CrossAccountId, @@ -726,16 +736,23 @@ to: &T::CrossAccountId, amount: u128, nesting_budget: &dyn Budget, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let allowance = Self::check_allowed(collection, spender, from, amount, nesting_budget)?; // ========= - Self::transfer(collection, from, to, amount, nesting_budget)?; + let mut result = Self::transfer(collection, from, to, amount, nesting_budget); + add_weight_to_post_info(&mut result, >::check_allowed_raw()); + result?; + if let Some(allowance) = allowance { Self::set_allowance_unchecked(collection, from, spender, allowance); + add_weight_to_post_info( + &mut result, + >::set_allowance_unchecked_raw(), + ) } - Ok(()) + result } /// Burn fungible tokens from the account. --- a/pallets/fungible/src/weights.rs +++ b/pallets/fungible/src/weights.rs @@ -37,10 +37,11 @@ fn create_item() -> Weight; fn create_multiple_items_ex(b: u32, ) -> Weight; fn burn_item() -> Weight; - fn transfer() -> Weight; + fn transfer_raw() -> Weight; fn approve() -> Weight; fn approve_from() -> Weight; - fn transfer_from() -> Weight; + fn check_allowed_raw() -> Weight; + fn set_allowance_unchecked_raw() -> Weight; fn burn_from() -> Weight; } @@ -94,12 +95,12 @@ } /// Storage: Fungible Balance (r:2 w:2) /// Proof: Fungible Balance (max_values: None, max_size: Some(77), added: 2552, mode: MaxEncodedLen) - fn transfer() -> Weight { + fn transfer_raw() -> Weight { // Proof Size summary in bytes: // Measured: `182` // Estimated: `5104` - // Minimum execution time: 13_832_000 picoseconds. - Weight::from_parts(14_064_000, 5104) + // Minimum execution time: 6_678_000 picoseconds. + Weight::from_parts(7_151_000, 5104) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -129,19 +130,26 @@ .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Fungible Allowance (r:1 w:1) + /// Storage: Fungible Allowance (r:1 w:0) /// Proof: Fungible Allowance (max_values: None, max_size: Some(93), added: 2568, mode: MaxEncodedLen) - /// Storage: Fungible Balance (r:2 w:2) - /// Proof: Fungible Balance (max_values: None, max_size: Some(77), added: 2552, mode: MaxEncodedLen) - fn transfer_from() -> Weight { + fn check_allowed_raw() -> Weight { // Proof Size summary in bytes: - // Measured: `300` - // Estimated: `7672` - // Minimum execution time: 21_667_000 picoseconds. - Weight::from_parts(22_166_000, 7672) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + // Measured: `210` + // Estimated: `2568` + // Minimum execution time: 2_842_000 picoseconds. + Weight::from_parts(3_077_000, 2568) + .saturating_add(T::DbWeight::get().reads(1_u64)) } + /// Storage: Fungible Allowance (r:0 w:1) + /// Proof: Fungible Allowance (max_values: None, max_size: Some(93), added: 2568, mode: MaxEncodedLen) + fn set_allowance_unchecked_raw() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_532_000 picoseconds. + Weight::from_parts(2_680_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } /// Storage: Fungible Allowance (r:1 w:1) /// Proof: Fungible Allowance (max_values: None, max_size: Some(93), added: 2568, mode: MaxEncodedLen) /// Storage: Fungible TotalSupply (r:1 w:1) @@ -208,12 +216,12 @@ } /// Storage: Fungible Balance (r:2 w:2) /// Proof: Fungible Balance (max_values: None, max_size: Some(77), added: 2552, mode: MaxEncodedLen) - fn transfer() -> Weight { + fn transfer_raw() -> Weight { // Proof Size summary in bytes: // Measured: `182` // Estimated: `5104` - // Minimum execution time: 13_832_000 picoseconds. - Weight::from_parts(14_064_000, 5104) + // Minimum execution time: 6_678_000 picoseconds. + Weight::from_parts(7_151_000, 5104) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -243,18 +251,25 @@ .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Fungible Allowance (r:1 w:1) + /// Storage: Fungible Allowance (r:1 w:0) /// Proof: Fungible Allowance (max_values: None, max_size: Some(93), added: 2568, mode: MaxEncodedLen) - /// Storage: Fungible Balance (r:2 w:2) - /// Proof: Fungible Balance (max_values: None, max_size: Some(77), added: 2552, mode: MaxEncodedLen) - fn transfer_from() -> Weight { + fn check_allowed_raw() -> Weight { // Proof Size summary in bytes: - // Measured: `300` - // Estimated: `7672` - // Minimum execution time: 21_667_000 picoseconds. - Weight::from_parts(22_166_000, 7672) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + // Measured: `210` + // Estimated: `2568` + // Minimum execution time: 2_842_000 picoseconds. + Weight::from_parts(3_077_000, 2568) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: Fungible Allowance (r:0 w:1) + /// Proof: Fungible Allowance (max_values: None, max_size: Some(93), added: 2568, mode: MaxEncodedLen) + fn set_allowance_unchecked_raw() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_532_000 picoseconds. + Weight::from_parts(2_680_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: Fungible Allowance (r:1 w:1) /// Proof: Fungible Allowance (max_values: None, max_size: Some(93), added: 2568, mode: MaxEncodedLen) --- a/pallets/nonfungible/CHANGELOG.md +++ b/pallets/nonfungible/CHANGELOG.md @@ -4,6 +4,12 @@ +## [0.1.14] - 2023-03-28 + +### Fixed + +- The weight of `transfer` and `transfer_from`. + ## [0.1.13] - 2023-01-20 ### Fixed --- a/pallets/nonfungible/Cargo.toml +++ b/pallets/nonfungible/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" license = "GPLv3" name = "pallet-nonfungible" -version = "0.1.13" +version = "0.1.14" [dependencies] # Note: `package = "parity-scale-codec"` must be supplied since the `Encode` macro searches for it. --- a/pallets/nonfungible/src/benchmarking.rs +++ b/pallets/nonfungible/src/benchmarking.rs @@ -121,7 +121,7 @@ } }: {>::burn_recursively(&collection, &burner, item, &Unlimited, &Unlimited)?} - transfer { + transfer_raw { bench_init!{ owner: sub; collection: collection(owner); owner: cross_from_sub; sender: cross_sub; receiver: cross_sub; @@ -146,14 +146,14 @@ let item = create_max_item(&collection, &owner, owner_eth.clone())?; }: {>::set_allowance_from(&collection, &sender, &owner_eth, item, Some(&spender))?} - transfer_from { + check_allowed_raw { bench_init!{ owner: sub; collection: collection(owner); owner: cross_from_sub; sender: cross_sub; spender: cross_sub; receiver: cross_sub; }; let item = create_max_item(&collection, &owner, sender.clone())?; >::set_allowance(&collection, &sender, item, Some(&spender))?; - }: {>::transfer_from(&collection, &spender, &sender, &receiver, item, &Unlimited)?} + }: {>::check_allowed(&collection, &spender, &sender, item, &Unlimited)?} burn_from { bench_init!{ --- a/pallets/nonfungible/src/common.rs +++ b/pallets/nonfungible/src/common.rs @@ -23,7 +23,7 @@ }; use pallet_common::{ CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight, - weights::WeightInfo as _, + weights::WeightInfo as _, SelfWeightOf as PalletCommonWeightOf, }; use sp_runtime::DispatchError; use sp_std::{vec::Vec, vec}; @@ -91,7 +91,7 @@ } fn transfer() -> Weight { - >::transfer() + >::transfer_raw() + >::check_accesslist() * 2 } fn approve() -> Weight { @@ -103,7 +103,7 @@ } fn transfer_from() -> Weight { - >::transfer_from() + Self::transfer() + >::check_allowed_raw() } fn burn_from() -> Weight { @@ -325,10 +325,7 @@ ) -> DispatchResultWithPostInfo { ensure!(amount <= 1, >::NonfungibleItemsHaveNoAmount); if amount == 1 { - with_weight( - >::transfer(self, &from, &to, token, nesting_budget), - >::transfer(), - ) + >::transfer(self, &from, &to, token, nesting_budget) } else { >::check_token_immediate_ownership(self, token, &from)?; Ok(().into()) @@ -386,10 +383,7 @@ ensure!(amount <= 1, >::NonfungibleItemsHaveNoAmount); if amount == 1 { - with_weight( - >::transfer_from(self, &sender, &from, &to, token, nesting_budget), - >::transfer_from(), - ) + >::transfer_from(self, &sender, &from, &to, token, nesting_budget) } else { >::check_allowed(self, &sender, &from, token, nesting_budget)?; --- a/pallets/nonfungible/src/erc.rs +++ b/pallets/nonfungible/src/erc.rs @@ -39,6 +39,7 @@ CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations, erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key}, eth::{self, TokenUri}, + CommonWeightInfo, }; use pallet_evm::{account::CrossAccountId, PrecompileHandle}; use pallet_evm_coder_substrate::call; @@ -47,7 +48,7 @@ use crate::{ AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted, - TokenProperties, SelfWeightOf, weights::WeightInfo, + TokenProperties, SelfWeightOf, weights::WeightInfo, common::CommonWeights, }; /// Nft events. @@ -458,7 +459,7 @@ /// @param from The current owner of the NFT /// @param to The new owner /// @param tokenId The NFT to transfer - #[weight(>::transfer_from())] + #[weight(>::transfer_from())] fn transfer_from( &mut self, caller: Caller, @@ -475,7 +476,7 @@ .weight_calls_budget(>::find_parent()); >::transfer_from(self, &caller, &from, &to, token, &budget) - .map_err(dispatch_to_evm::)?; + .map_err(|e| dispatch_to_evm::(e.error))?; Ok(()) } @@ -824,7 +825,7 @@ /// is the zero address. Throws if `tokenId` is not a valid NFT. /// @param to The new owner /// @param tokenId The NFT to transfer - #[weight(>::transfer())] + #[weight(>::transfer())] fn transfer(&mut self, caller: Caller, to: Address, token_id: U256) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let to = T::CrossAccountId::from_eth(to); @@ -833,7 +834,8 @@ .recorder .weight_calls_budget(>::find_parent()); - >::transfer(self, &caller, &to, token, &budget).map_err(dispatch_to_evm::)?; + >::transfer(self, &caller, &to, token, &budget) + .map_err(|e| dispatch_to_evm::(e.error))?; Ok(()) } @@ -842,7 +844,7 @@ /// is the zero address. Throws if `tokenId` is not a valid NFT. /// @param to The new owner /// @param tokenId The NFT to transfer - #[weight(>::transfer())] + #[weight(>::transfer())] fn transfer_cross( &mut self, caller: Caller, @@ -856,7 +858,8 @@ .recorder .weight_calls_budget(>::find_parent()); - >::transfer(self, &caller, &to, token, &budget).map_err(dispatch_to_evm::)?; + >::transfer(self, &caller, &to, token, &budget) + .map_err(|e| dispatch_to_evm::(e.error))?; Ok(()) } @@ -866,7 +869,7 @@ /// @param from Cross acccount address of current owner /// @param to Cross acccount address of new owner /// @param tokenId The NFT to transfer - #[weight(>::transfer())] + #[weight(>::transfer_from())] fn transfer_from_cross( &mut self, caller: Caller, @@ -882,7 +885,7 @@ .recorder .weight_calls_budget(>::find_parent()); Pallet::::transfer_from(self, &caller, &from, &to, token_id, &budget) - .map_err(dispatch_to_evm::)?; + .map_err(|e| dispatch_to_evm::(e.error))?; Ok(()) } --- a/pallets/nonfungible/src/lib.rs +++ b/pallets/nonfungible/src/lib.rs @@ -108,7 +108,8 @@ use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm}; use pallet_common::{ Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, CollectionHandle, - eth::collection_id_to_address, + eth::collection_id_to_address, SelfWeightOf as PalletCommonWeightOf, + weights::WeightInfo as CommonWeightInfo, helpers::add_weight_to_post_info, }; use pallet_structure::{Pallet as PalletStructure, Error as StructureError}; use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder}; @@ -802,12 +803,13 @@ to: &T::CrossAccountId, token: TokenId, nesting_budget: &dyn Budget, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { ensure!( collection.limits.transfers_enabled(), >::TransferNotAllowed ); + let mut actual_weight = >::transfer_raw(); let token_data = >::get((collection.id, token)).ok_or(>::TokenNotFound)?; ensure!(&token_data.owner == from, >::NoPermission); @@ -815,6 +817,7 @@ if collection.permissions.access() == AccessMode::AllowList { collection.check_allowlist(from)?; collection.check_allowlist(to)?; + actual_weight += >::check_accesslist() * 2; } >::ensure_correct_receiver(to)?; @@ -884,7 +887,11 @@ to.clone(), 1, )); - Ok(()) + + Ok(PostDispatchInfo { + actual_weight: Some(actual_weight), + pays_fee: Pays::Yes, + }) } /// Batch operation to mint multiple NFT tokens. @@ -1228,13 +1235,15 @@ to: &T::CrossAccountId, token: TokenId, nesting_budget: &dyn Budget, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { Self::check_allowed(collection, spender, from, token, nesting_budget)?; // ========= // Allowance is reset in [`transfer`] - Self::transfer(collection, from, to, token, nesting_budget) + let mut result = Self::transfer(collection, from, to, token, nesting_budget); + add_weight_to_post_info(&mut result, >::check_allowed_raw()); + result } /// Burn NFT token for `from` account. --- a/pallets/nonfungible/src/weights.rs +++ b/pallets/nonfungible/src/weights.rs @@ -40,10 +40,10 @@ fn burn_item() -> Weight; fn burn_recursively_self_raw() -> Weight; fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight; - fn transfer() -> Weight; + fn transfer_raw() -> Weight; fn approve() -> Weight; fn approve_from() -> Weight; - fn transfer_from() -> Weight; + fn check_allowed_raw() -> Weight; fn burn_from() -> Weight; fn set_token_property_permissions(b: u32, ) -> Weight; fn set_token_properties(b: u32, ) -> Weight; @@ -217,12 +217,12 @@ /// Proof: Nonfungible Allowance (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) /// Storage: Nonfungible Owned (r:0 w:2) /// Proof: Nonfungible Owned (max_values: None, max_size: Some(74), added: 2549, mode: MaxEncodedLen) - fn transfer() -> Weight { + fn transfer_raw() -> Weight { // Proof Size summary in bytes: // Measured: `412` // Estimated: `10144` - // Minimum execution time: 18_629_000 picoseconds. - Weight::from_parts(18_997_000, 10144) + // Minimum execution time: 9_307_000 picoseconds. + Weight::from_parts(10_108_000, 10144) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -252,22 +252,15 @@ .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: Nonfungible Allowance (r:1 w:1) + /// Storage: Nonfungible Allowance (r:1 w:0) /// Proof: Nonfungible Allowance (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) - /// Storage: Nonfungible TokenData (r:1 w:1) - /// Proof: Nonfungible TokenData (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) - /// Storage: Nonfungible AccountBalance (r:2 w:2) - /// Proof: Nonfungible AccountBalance (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - /// Storage: Nonfungible Owned (r:0 w:2) - /// Proof: Nonfungible Owned (max_values: None, max_size: Some(74), added: 2549, mode: MaxEncodedLen) - fn transfer_from() -> Weight { + fn check_allowed_raw() -> Weight { // Proof Size summary in bytes: - // Measured: `527` - // Estimated: `10144` - // Minimum execution time: 24_919_000 picoseconds. - Weight::from_parts(25_333_000, 10144) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) + // Measured: `394` + // Estimated: `2532` + // Minimum execution time: 2_668_000 picoseconds. + Weight::from_parts(2_877_000, 2532) + .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: Nonfungible Allowance (r:1 w:1) /// Proof: Nonfungible Allowance (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) @@ -543,12 +536,12 @@ /// Proof: Nonfungible Allowance (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) /// Storage: Nonfungible Owned (r:0 w:2) /// Proof: Nonfungible Owned (max_values: None, max_size: Some(74), added: 2549, mode: MaxEncodedLen) - fn transfer() -> Weight { + fn transfer_raw() -> Weight { // Proof Size summary in bytes: // Measured: `412` // Estimated: `10144` - // Minimum execution time: 18_629_000 picoseconds. - Weight::from_parts(18_997_000, 10144) + // Minimum execution time: 9_307_000 picoseconds. + Weight::from_parts(10_108_000, 10144) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -578,22 +571,15 @@ .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: Nonfungible Allowance (r:1 w:1) + /// Storage: Nonfungible Allowance (r:1 w:0) /// Proof: Nonfungible Allowance (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) - /// Storage: Nonfungible TokenData (r:1 w:1) - /// Proof: Nonfungible TokenData (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen) - /// Storage: Nonfungible AccountBalance (r:2 w:2) - /// Proof: Nonfungible AccountBalance (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - /// Storage: Nonfungible Owned (r:0 w:2) - /// Proof: Nonfungible Owned (max_values: None, max_size: Some(74), added: 2549, mode: MaxEncodedLen) - fn transfer_from() -> Weight { + fn check_allowed_raw() -> Weight { // Proof Size summary in bytes: - // Measured: `527` - // Estimated: `10144` - // Minimum execution time: 24_919_000 picoseconds. - Weight::from_parts(25_333_000, 10144) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + // Measured: `394` + // Estimated: `2532` + // Minimum execution time: 2_668_000 picoseconds. + Weight::from_parts(2_877_000, 2532) + .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: Nonfungible Allowance (r:1 w:1) /// Proof: Nonfungible Allowance (max_values: None, max_size: Some(57), added: 2532, mode: MaxEncodedLen)