difftreelog
feat budgets
in: master
19 files changed
pallets/common/src/lib.rsdiffbeforeafterboth33 COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, TokenId, CollectionStats, MAX_TOKEN_OWNERSHIP,33 COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, TokenId, CollectionStats, MAX_TOKEN_OWNERSHIP,34 CollectionMode, NFT_SPONSOR_TRANSFER_TIMEOUT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,34 CollectionMode, NFT_SPONSOR_TRANSFER_TIMEOUT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,35 REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MAX_SPONSOR_TIMEOUT, CUSTOM_DATA_LIMIT, CollectionLimits,35 REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MAX_SPONSOR_TIMEOUT, CUSTOM_DATA_LIMIT, CollectionLimits,36 CustomDataLimit, CreateCollectionData, SponsorshipState, CreateItemExData, SponsoringRateLimit,36 CustomDataLimit, CreateCollectionData, SponsorshipState, CreateItemExData, SponsoringRateLimit, budget::Budget,37};37};38pub use pallet::*;38pub use pallet::*;39use sp_core::H160;39use sp_core::H160;763 to: T::CrossAccountId,763 to: T::CrossAccountId,764 token: TokenId,764 token: TokenId,765 amount: u128,765 amount: u128,766 nesting_budget: &dyn Budget,766 ) -> DispatchResultWithPostInfo;767 ) -> DispatchResultWithPostInfo;767 fn burn_from(768 fn burn_from(768 &self,769 &self,769 sender: T::CrossAccountId,770 sender: T::CrossAccountId,770 from: T::CrossAccountId,771 from: T::CrossAccountId,771 token: TokenId,772 token: TokenId,772 amount: u128,773 amount: u128,774 nesting_budget: &dyn Budget,773 ) -> DispatchResultWithPostInfo;775 ) -> DispatchResultWithPostInfo;774776775 fn set_variable_metadata(777 fn set_variable_metadata(pallets/evm-coder-substrate/Cargo.tomldiffbeforeafterboth17frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" }17frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" }18frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" }18frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" }19frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" }19frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" }20up-data-structs = { default-features = false, path = "../../primitives/data-structs" }202121[dependencies.codec]22[dependencies.codec]22default-features = false23default-features = falsepallets/evm-coder-substrate/src/lib.rsdiffbeforeafterboth181819#[cfg(not(feature = "std"))]19#[cfg(not(feature = "std"))]20extern crate alloc;20extern crate alloc;21// #[cfg(feature = "runtime-benchmarks")]22// pub mod benchmarking;2324pub use pallet::*;2526#[frame_support::pallet]27pub mod pallet {28 #[cfg(not(feature = "std"))]21#[cfg(not(feature = "std"))]29 use alloc::format;22use alloc::format;3031 use evm_coder::{23use frame_support::dispatch::Weight;32 ToLog,2433 abi::{AbiReader, AbiWrite, AbiWriter},25use core::marker::PhantomData;34 execution::{self, Result},35 types::{Msg, value},26use sp_std::cell::RefCell;36 };27use sp_std::vec::Vec;2829use frame_support::pallet_prelude::DispatchError;30use frame_support::traits::PalletInfo;37 use frame_support::{ensure, sp_runtime::ModuleError};31use frame_support::{ensure, sp_runtime::ModuleError};32use up_data_structs::budget;38 use pallet_evm::{33use pallet_evm::{39 ExitError, ExitRevert, ExitSucceed, GasWeightMapping, PrecompileFailure, PrecompileOutput,34 ExitError, ExitRevert, ExitSucceed, GasWeightMapping, PrecompileFailure, PrecompileOutput,40 PrecompileResult, runner::stack::MaybeMirroredLog,35 PrecompileResult, runner::stack::MaybeMirroredLog,41 };36};42 use frame_system::ensure_signed;37use ethereum::TransactionV2;43 pub use frame_support::dispatch::DispatchResult;38use sp_core::{H160, H256};44 use pallet_ethereum::EthereumTransactionSender;39use pallet_ethereum::EthereumTransactionSender;40// #[cfg(feature = "runtime-benchmarks")]41// pub mod benchmarking;4245 use sp_std::cell::RefCell;43use evm_coder::{44 ToLog,45 abi::{AbiReader, AbiWrite, AbiWriter},46 execution::{self, Result},47 types::{Msg, value},48};4946 use sp_std::vec::Vec;50pub use pallet::*;5152#[frame_support::pallet]53pub mod pallet {54 use super::*;5547 use sp_core::H160;56 use frame_system::ensure_signed;57 pub use frame_support::dispatch::DispatchResult;48 use frame_support::{pallet_prelude::*, traits::PalletInfo};58 use frame_support::{pallet_prelude::*, traits::PalletInfo};49 use frame_system::pallet_prelude::*;59 use frame_system::pallet_prelude::*;506076 Ok(())86 Ok(())77 }87 }78 }88 }89}799080 // From instabul hardfork configuration: https://github.com/rust-blockchain/evm/blob/fd4fd6acc0ca3208d6770fdb3ba407c94cdf97c6/runtime/src/lib.rs#L28491// From instabul hardfork configuration: https://github.com/rust-blockchain/evm/blob/fd4fd6acc0ca3208d6770fdb3ba407c94cdf97c6/runtime/src/lib.rs#L28481 pub const G_SLOAD_WORD: u64 = 800;92pub const G_SLOAD_WORD: u64 = 800;82 pub const G_SSTORE_WORD: u64 = 20000;93pub const G_SSTORE_WORD: u64 = 20000;9495pub fn generate_transaction() -> TransactionV2 {96 use ethereum::{TransactionV0, TransactionAction, TransactionSignature};97 TransactionV2::Legacy(TransactionV0 {98 nonce: 0.into(),99 gas_price: 0.into(),100 gas_limit: 0.into(),101 action: TransactionAction::Call(H160([0; 20])),102 value: 0.into(),103 // zero selector, this transaction always has same sender, so all data should be acquired from logs104 input: Vec::from([0, 0, 0, 0]),105 // if v is not 27 - then we need to pass some other validity checks106 signature: TransactionSignature::new(27, H256([0x88; 32]), H256([0x88; 32])).unwrap(),107 })108}109110pub struct GasCallsBudget<'r, T: Config> {111 recorder: &'r SubstrateRecorder<T>,112 gas_per_call: u64,113}114impl<T: Config> budget::Budget for GasCallsBudget<'_, T> {115 fn consume_custom(&self, calls: u32) -> bool {116 let (gas, overflown) = (calls as u64).overflowing_add(self.gas_per_call);117 if overflown {118 return false;119 }120 self.recorder.consume_gas(gas).is_ok()121 }122}8312384 #[derive(Default)]124#[derive(Default)]85 pub struct SubstrateRecorder<T: Config> {125pub struct SubstrateRecorder<T: Config> {123 pub fn gas_left(&self) -> u64 {163 pub fn gas_left(&self) -> u64 {124 *self.gas_limit.borrow()164 *self.gas_limit.borrow()125 }165 }166 pub fn gas_calls_budget(&self, gas_per_call: u64) -> GasCallsBudget<T> {167 GasCallsBudget {168 recorder: self,169 gas_per_call,170 }171 }172 pub fn weight_calls_budget(&self, weight_per_call: Weight) -> GasCallsBudget<T> {173 GasCallsBudget {174 recorder: self,175 gas_per_call: T::GasWeightMapping::weight_to_gas(weight_per_call),176 }177 }126 pub fn consume_sload_sub(&self) -> DispatchResult {178 pub fn consume_sload_sub(&self) -> DispatchResult {127 self.consume_gas_sub(G_SLOAD_WORD)179 self.consume_gas_sub(G_SLOAD_WORD)128 }180 }198 }250 }199 T::EthereumTransactionSender::submit_logs_transaction(Default::default(), logs)251 T::EthereumTransactionSender::submit_logs_transaction(252 Default::default(),253 generate_transaction(),254 logs,255 )200 }256 }201 }257}209 .expect("evm-coder-substrate is a pallet, which should be added to runtime")265 .expect("evm-coder-substrate is a pallet, which should be added to runtime")210 as u8 =>266 as u8 =>211 {267 {212 let mut read = &error as &[u8];213 match Error::<T>::decode(&mut read) {268 match error {214 Ok(Error::<T>::OutOfGas) => ExError::Error(ExitError::OutOfGas),269 v if v == Error::<T>::OutOfGas.as_u8() => ExError::Error(ExitError::OutOfGas),215 Ok(Error::<T>::OutOfFund) => ExError::Error(ExitError::OutOfFund),270 v if v == Error::<T>::OutOfFund.as_u8() => ExError::Error(ExitError::OutOfFund),216 _ => unreachable!("this pallet only defines two possible errors"),271 _ => unreachable!("this pallet only defines two possible errors"),217 }272 }218 }273 }219 DispatchError::Module(ModuleError {274 DispatchError::Module(ModuleError {220 message: Some(msg), ..275 message: Some(msg), ..221 }) => ExError::Revert(msg.into()),276 }) => ExError::Revert(msg.into()),222 DispatchError::Module(ModuleError { index, error, .. }) => {277 DispatchError::Module(ModuleError { index, error, .. }) => {223 ExError::Revert(format!("error {:?} in pallet {}", error, index))278 ExError::Revert(format!("error {} in pallet {}", error, index))224 }279 }225 e => ExError::Revert(format!("substrate error: {:?}", e)),280 e => ExError::Revert(format!("substrate error: {:?}", e)),226 }281 }286 }341 }287 }342 }288 }343}289}290344pallets/fungible/src/benchmarking.rsdiffbeforeafterboth20use sp_std::prelude::*;20use sp_std::prelude::*;21use pallet_common::benchmarking::create_collection_raw;21use pallet_common::benchmarking::create_collection_raw;22use frame_benchmarking::{benchmarks, account};22use frame_benchmarking::{benchmarks, account};23use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH};23use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, budget::Unlimited};24use pallet_common::bench_init;24use pallet_common::bench_init;252526const SEED: u32 = 1;26const SEED: u32 = 1;52 bench_init!(to: cross_sub(i););52 bench_init!(to: cross_sub(i););53 (to, 200)53 (to, 200)54 }).collect::<BTreeMap<_, _>>().try_into().unwrap();54 }).collect::<BTreeMap<_, _>>().try_into().unwrap();55 }: {<Pallet<T>>::create_multiple_items(&collection, &sender, data)}55 }: {<Pallet<T>>::create_multiple_items(&collection, &sender, data)?}565657 burn_item {57 burn_item {58 bench_init!{58 bench_init!{85 };85 };86 <Pallet<T>>::create_item(&collection, &owner, (sender.clone(), 200))?;86 <Pallet<T>>::create_item(&collection, &owner, (sender.clone(), 200))?;87 <Pallet<T>>::set_allowance(&collection, &sender, &spender, 200)?;87 <Pallet<T>>::set_allowance(&collection, &sender, &spender, 200)?;88 }: {<Pallet<T>>::transfer_from(&collection, &spender, &sender, &receiver, 100)?}88 }: {<Pallet<T>>::transfer_from(&collection, &spender, &sender, &receiver, 100, &Unlimited)?}898990 burn_from {90 burn_from {91 bench_init!{91 bench_init!{94 };94 };95 <Pallet<T>>::create_item(&collection, &owner, (sender.clone(), 200))?;95 <Pallet<T>>::create_item(&collection, &owner, (sender.clone(), 200))?;96 <Pallet<T>>::set_allowance(&collection, &sender, &burner, 200)?;96 <Pallet<T>>::set_allowance(&collection, &sender, &burner, 200)?;97 }: {<Pallet<T>>::burn_from(&collection, &burner, &sender, 100)?}97 }: {<Pallet<T>>::burn_from(&collection, &burner, &sender, 100, &Unlimited)?}98}98}9999pallets/fungible/src/common.rsdiffbeforeafterboth17use core::marker::PhantomData;17use core::marker::PhantomData;181819use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};19use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};20use up_data_structs::{TokenId, CreateItemExData};20use up_data_structs::{TokenId, CreateItemExData, budget::Budget};21use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};21use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};22use sp_runtime::ArithmeticError;22use sp_runtime::ArithmeticError;23use sp_std::{vec::Vec, vec};23use sp_std::{vec::Vec, vec};189 to: T::CrossAccountId,189 to: T::CrossAccountId,190 token: TokenId,190 token: TokenId,191 amount: u128,191 amount: u128,192 nesting_budget: &dyn Budget,192 ) -> DispatchResultWithPostInfo {193 ) -> DispatchResultWithPostInfo {193 ensure!(194 ensure!(194 token == TokenId::default(),195 token == TokenId::default(),195 <Error<T>>::FungibleItemsHaveNoId196 <Error<T>>::FungibleItemsHaveNoId196 );197 );197198198 with_weight(199 with_weight(199 <Pallet<T>>::transfer_from(self, &sender, &from, &to, amount),200 <Pallet<T>>::transfer_from(self, &sender, &from, &to, amount, nesting_budget),200 <CommonWeights<T>>::transfer_from(),201 <CommonWeights<T>>::transfer_from(),201 )202 )202 }203 }207 from: T::CrossAccountId,208 from: T::CrossAccountId,208 token: TokenId,209 token: TokenId,209 amount: u128,210 amount: u128,211 nesting_budget: &dyn Budget,210 ) -> DispatchResultWithPostInfo {212 ) -> DispatchResultWithPostInfo {211 ensure!(213 ensure!(212 token == TokenId::default(),214 token == TokenId::default(),213 <Error<T>>::FungibleItemsHaveNoId215 <Error<T>>::FungibleItemsHaveNoId214 );216 );215217216 with_weight(218 with_weight(217 <Pallet<T>>::burn_from(self, &sender, &from, amount),219 <Pallet<T>>::burn_from(self, &sender, &from, amount, nesting_budget),218 <CommonWeights<T>>::burn_from(),220 <CommonWeights<T>>::burn_from(),219 )221 )220 }222 }pallets/fungible/src/erc.rsdiffbeforeafterboth23use sp_std::vec::Vec;23use sp_std::vec::Vec;24use pallet_evm::account::CrossAccountId;24use pallet_evm::account::CrossAccountId;25use pallet_evm_coder_substrate::{call, dispatch_to_evm};25use pallet_evm_coder_substrate::{call, dispatch_to_evm};26use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};262727use crate::{28use crate::{28 Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply,29 Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply,96 let from = T::CrossAccountId::from_eth(from);97 let from = T::CrossAccountId::from_eth(from);97 let to = T::CrossAccountId::from_eth(to);98 let to = T::CrossAccountId::from_eth(to);98 let amount = amount.try_into().map_err(|_| "amount overflow")?;99 let amount = amount.try_into().map_err(|_| "amount overflow")?;100 let budget = self101 .recorder102 .weight_calls_budget(<StructureWeight<T>>::find_parent());99103100 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount)104 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)101 .map_err(dispatch_to_evm::<T>)?;105 .map_err(dispatch_to_evm::<T>)?;102 Ok(true)106 Ok(true)103 }107 }127 let caller = T::CrossAccountId::from_eth(caller);131 let caller = T::CrossAccountId::from_eth(caller);128 let from = T::CrossAccountId::from_eth(from);132 let from = T::CrossAccountId::from_eth(from);129 let amount = amount.try_into().map_err(|_| "amount overflow")?;133 let amount = amount.try_into().map_err(|_| "amount overflow")?;134 let budget = self135 .recorder136 .weight_calls_budget(<StructureWeight<T>>::find_parent());130137131 <Pallet<T>>::burn_from(self, &caller, &from, amount).map_err(dispatch_to_evm::<T>)?;138 <Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)139 .map_err(dispatch_to_evm::<T>)?;132 Ok(true)140 Ok(true)133 }141 }pallets/fungible/src/lib.rsdiffbeforeafterboth21use pallet_evm::account::CrossAccountId;21use pallet_evm::account::CrossAccountId;22use up_data_structs::{22use up_data_structs::{23 AccessMode, CollectionId, TokenId, CreateCollectionData, mapping::TokenAddressMapping,23 AccessMode, CollectionId, TokenId, CreateCollectionData, mapping::TokenAddressMapping,24 budget::Budget,24};25};25use pallet_common::{26use pallet_common::{26 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,27 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,361 spender: &T::CrossAccountId,362 spender: &T::CrossAccountId,362 from: &T::CrossAccountId,363 from: &T::CrossAccountId,363 amount: u128,364 amount: u128,365 nesting_budget: &dyn Budget,364 ) -> Result<Option<u128>, DispatchError> {366 ) -> Result<Option<u128>, DispatchError> {365 if spender.conv_eq(from) {367 if spender.conv_eq(from) {366 return Ok(None);368 return Ok(None);372 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {374 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {373 // TODO: should collection owner be allowed to perform this transfer?375 // TODO: should collection owner be allowed to perform this transfer?374 ensure!(376 ensure!(375 <PalletStructure<T>>::indirectly_owned(spender.clone(), source.0, source.1, 1)?,377 <PalletStructure<T>>::indirectly_owned(378 spender.clone(),379 source.0,380 source.1,381 nesting_budget382 )?,376 <CommonError<T>>::ApprovedValueTooLow,383 <CommonError<T>>::ApprovedValueTooLow,377 );384 );394 from: &T::CrossAccountId,401 from: &T::CrossAccountId,395 to: &T::CrossAccountId,402 to: &T::CrossAccountId,396 amount: u128,403 amount: u128,404 nesting_budget: &dyn Budget,397 ) -> DispatchResult {405 ) -> DispatchResult {398 let allowance = Self::check_allowed(collection, spender, from, amount)?;406 let allowance = Self::check_allowed(collection, spender, from, amount, nesting_budget)?;399407400 // =========408 // =========401409411 spender: &T::CrossAccountId,419 spender: &T::CrossAccountId,412 from: &T::CrossAccountId,420 from: &T::CrossAccountId,413 amount: u128,421 amount: u128,422 nesting_budget: &dyn Budget,414 ) -> DispatchResult {423 ) -> DispatchResult {415 let allowance = Self::check_allowed(collection, spender, from, amount)?;424 let allowance = Self::check_allowed(collection, spender, from, amount, nesting_budget)?;416425417 // =========426 // =========418427pallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth20use sp_std::prelude::*;20use sp_std::prelude::*;21use pallet_common::benchmarking::{create_collection_raw, create_data, create_var_data};21use pallet_common::benchmarking::{create_collection_raw, create_data, create_var_data};22use frame_benchmarking::{benchmarks, account};22use frame_benchmarking::{benchmarks, account};23use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, CUSTOM_DATA_LIMIT};23use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, CUSTOM_DATA_LIMIT, budget::Unlimited};24use pallet_common::bench_init;24use pallet_common::bench_init;25use core::convert::TryInto;25use core::convert::TryInto;2626115 };115 };116 let item = create_max_item(&collection, &owner, sender.clone())?;116 let item = create_max_item(&collection, &owner, sender.clone())?;117 <Pallet<T>>::set_allowance(&collection, &sender, item, Some(&spender))?;117 <Pallet<T>>::set_allowance(&collection, &sender, item, Some(&spender))?;118 }: {<Pallet<T>>::transfer_from(&collection, &spender, &sender, &receiver, item)?}118 }: {<Pallet<T>>::transfer_from(&collection, &spender, &sender, &receiver, item, &Unlimited)?}119119120 burn_from {120 burn_from {121 bench_init!{121 bench_init!{124 };124 };125 let item = create_max_item(&collection, &owner, sender.clone())?;125 let item = create_max_item(&collection, &owner, sender.clone())?;126 <Pallet<T>>::set_allowance(&collection, &sender, item, Some(&burner))?;126 <Pallet<T>>::set_allowance(&collection, &sender, item, Some(&burner))?;127 }: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item)?}127 }: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, &Unlimited)?}128128129 set_variable_metadata {129 set_variable_metadata {130 let b in 0..CUSTOM_DATA_LIMIT;130 let b in 0..CUSTOM_DATA_LIMIT;pallets/nonfungible/src/common.rsdiffbeforeafterboth17use core::marker::PhantomData;17use core::marker::PhantomData;181819use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};19use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};20use up_data_structs::{TokenId, CustomDataLimit, CreateItemExData, CollectionId};20use up_data_structs::{TokenId, CustomDataLimit, CreateItemExData, CollectionId, budget::Budget};21use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};21use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};22use sp_runtime::DispatchError;22use sp_runtime::DispatchError;23use sp_std::vec::Vec;23use sp_std::vec::Vec;192 to: T::CrossAccountId,192 to: T::CrossAccountId,193 token: TokenId,193 token: TokenId,194 amount: u128,194 amount: u128,195 nesting_budget: &dyn Budget,195 ) -> DispatchResultWithPostInfo {196 ) -> DispatchResultWithPostInfo {196 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);197 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);197198198 if amount == 1 {199 if amount == 1 {199 with_weight(200 with_weight(200 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token),201 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token, nesting_budget),201 <CommonWeights<T>>::transfer_from(),202 <CommonWeights<T>>::transfer_from(),202 )203 )203 } else {204 } else {211 from: T::CrossAccountId,212 from: T::CrossAccountId,212 token: TokenId,213 token: TokenId,213 amount: u128,214 amount: u128,215 nesting_budget: &dyn Budget,214 ) -> DispatchResultWithPostInfo {216 ) -> DispatchResultWithPostInfo {215 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);217 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);216218217 if amount == 1 {219 if amount == 1 {218 with_weight(220 with_weight(219 <Pallet<T>>::burn_from(self, &sender, &from, token),221 <Pallet<T>>::burn_from(self, &sender, &from, token, nesting_budget),220 <CommonWeights<T>>::burn_from(),222 <CommonWeights<T>>::burn_from(),221 )223 )222 } else {224 } else {pallets/nonfungible/src/erc.rsdiffbeforeafterboth30};30};31use pallet_evm::account::CrossAccountId;31use pallet_evm::account::CrossAccountId;32use pallet_evm_coder_substrate::call;32use pallet_evm_coder_substrate::call;33use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};333434use crate::{35use crate::{35 AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,36 AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,180 let from = T::CrossAccountId::from_eth(from);181 let from = T::CrossAccountId::from_eth(from);181 let to = T::CrossAccountId::from_eth(to);182 let to = T::CrossAccountId::from_eth(to);182 let token = token_id.try_into()?;183 let token = token_id.try_into()?;184 let budget = self185 .recorder186 .weight_calls_budget(<StructureWeight<T>>::find_parent());183187184 <Pallet<T>>::transfer_from(self, &caller, &from, &to, token)188 <Pallet<T>>::transfer_from(self, &caller, &from, &to, token, &budget)185 .map_err(dispatch_to_evm::<T>)?;189 .map_err(dispatch_to_evm::<T>)?;186 Ok(())190 Ok(())187 }191 }350 let caller = T::CrossAccountId::from_eth(caller);354 let caller = T::CrossAccountId::from_eth(caller);351 let from = T::CrossAccountId::from_eth(from);355 let from = T::CrossAccountId::from_eth(from);352 let token = token_id.try_into()?;356 let token = token_id.try_into()?;357 let budget = self358 .recorder359 .weight_calls_budget(<StructureWeight<T>>::find_parent());353360354 <Pallet<T>>::burn_from(self, &caller, &from, token).map_err(dispatch_to_evm::<T>)?;361 <Pallet<T>>::burn_from(self, &caller, &from, token, &budget)362 .map_err(dispatch_to_evm::<T>)?;355 Ok(())363 Ok(())356 }364 }pallets/nonfungible/src/lib.rsdiffbeforeafterboth20use frame_support::{BoundedVec, ensure, fail};20use frame_support::{BoundedVec, ensure, fail};21use up_data_structs::{21use up_data_structs::{22 AccessMode, CollectionId, CustomDataLimit, TokenId, CreateCollectionData, CreateNftExData,22 AccessMode, CollectionId, CustomDataLimit, TokenId, CreateCollectionData, CreateNftExData,23 mapping::TokenAddressMapping, NestingRule,23 mapping::TokenAddressMapping, NestingRule, budget::Budget,24};24};25use pallet_evm::account::CrossAccountId;25use pallet_evm::account::CrossAccountId;26use pallet_common::{26use pallet_common::{511 spender: &T::CrossAccountId,511 spender: &T::CrossAccountId,512 from: &T::CrossAccountId,512 from: &T::CrossAccountId,513 token: TokenId,513 token: TokenId,514 nesting_budget: &dyn Budget,514 ) -> DispatchResult {515 ) -> DispatchResult {515 if spender.conv_eq(from) {516 if spender.conv_eq(from) {516 return Ok(());517 return Ok(());522 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {523 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {523 // TODO: should collection owner be allowed to perform this transfer?524 // TODO: should collection owner be allowed to perform this transfer?524 ensure!(525 ensure!(525 <PalletStructure<T>>::indirectly_owned(spender.clone(), source.0, source.1, 1)?,526 <PalletStructure<T>>::indirectly_owned(527 spender.clone(),528 source.0,529 source.1,530 nesting_budget531 )?,526 <CommonError<T>>::ApprovedValueTooLow,532 <CommonError<T>>::ApprovedValueTooLow,527 );533 );543 from: &T::CrossAccountId,549 from: &T::CrossAccountId,544 to: &T::CrossAccountId,550 to: &T::CrossAccountId,545 token: TokenId,551 token: TokenId,552 nesting_budget: &dyn Budget,546 ) -> DispatchResult {553 ) -> DispatchResult {547 Self::check_allowed(collection, spender, from, token)?;554 Self::check_allowed(collection, spender, from, token, nesting_budget)?;548555549 // =========556 // =========550557557 spender: &T::CrossAccountId,564 spender: &T::CrossAccountId,558 from: &T::CrossAccountId,565 from: &T::CrossAccountId,559 token: TokenId,566 token: TokenId,567 nesting_budget: &dyn Budget,560 ) -> DispatchResult {568 ) -> DispatchResult {561 Self::check_allowed(collection, spender, from, token)?;569 Self::check_allowed(collection, spender, from, token, nesting_budget)?;562570563 // =========571 // =========564572pallets/refungible/src/benchmarking.rsdiffbeforeafterboth20use sp_std::prelude::*;20use sp_std::prelude::*;21use pallet_common::benchmarking::{create_collection_raw, create_data, create_var_data};21use pallet_common::benchmarking::{create_collection_raw, create_data, create_var_data};22use frame_benchmarking::{benchmarks, account};22use frame_benchmarking::{benchmarks, account};23use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, CUSTOM_DATA_LIMIT};23use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, CUSTOM_DATA_LIMIT, budget::Unlimited};24use pallet_common::bench_init;24use pallet_common::bench_init;25use core::convert::TryInto;25use core::convert::TryInto;26use core::iter::IntoIterator;26use core::iter::IntoIterator;165 };165 };166 let item = create_max_item(&collection, &owner, [(sender.clone(), 200), (receiver.clone(), 200)])?;166 let item = create_max_item(&collection, &owner, [(sender.clone(), 200), (receiver.clone(), 200)])?;167 <Pallet<T>>::set_allowance(&collection, &sender, &spender, item, 100)?;167 <Pallet<T>>::set_allowance(&collection, &sender, &spender, item, 100)?;168 }: {<Pallet<T>>::transfer_from(&collection, &spender, &sender, &receiver, item, 100)?}168 }: {<Pallet<T>>::transfer_from(&collection, &spender, &sender, &receiver, item, 100, &Unlimited)?}169 // Target account is created169 // Target account is created170 transfer_from_creating {170 transfer_from_creating {171 bench_init!{171 bench_init!{174 };174 };175 let item = create_max_item(&collection, &owner, [(sender.clone(), 200)])?;175 let item = create_max_item(&collection, &owner, [(sender.clone(), 200)])?;176 <Pallet<T>>::set_allowance(&collection, &sender, &spender, item, 100)?;176 <Pallet<T>>::set_allowance(&collection, &sender, &spender, item, 100)?;177 }: {<Pallet<T>>::transfer_from(&collection, &spender, &sender, &receiver, item, 100)?}177 }: {<Pallet<T>>::transfer_from(&collection, &spender, &sender, &receiver, item, 100, &Unlimited)?}178 // Source account is destroyed178 // Source account is destroyed179 transfer_from_removing {179 transfer_from_removing {180 bench_init!{180 bench_init!{183 };183 };184 let item = create_max_item(&collection, &owner, [(sender.clone(), 200), (receiver.clone(), 200)])?;184 let item = create_max_item(&collection, &owner, [(sender.clone(), 200), (receiver.clone(), 200)])?;185 <Pallet<T>>::set_allowance(&collection, &sender, &spender, item, 200)?;185 <Pallet<T>>::set_allowance(&collection, &sender, &spender, item, 200)?;186 }: {<Pallet<T>>::transfer_from(&collection, &spender, &sender, &receiver, item, 200)?}186 }: {<Pallet<T>>::transfer_from(&collection, &spender, &sender, &receiver, item, 200, &Unlimited)?}187 // Source account destroyed, target created187 // Source account destroyed, target created188 transfer_from_creating_removing {188 transfer_from_creating_removing {189 bench_init!{189 bench_init!{192 };192 };193 let item = create_max_item(&collection, &owner, [(sender.clone(), 200)])?;193 let item = create_max_item(&collection, &owner, [(sender.clone(), 200)])?;194 <Pallet<T>>::set_allowance(&collection, &sender, &spender, item, 200)?;194 <Pallet<T>>::set_allowance(&collection, &sender, &spender, item, 200)?;195 }: {<Pallet<T>>::transfer_from(&collection, &spender, &sender, &receiver, item, 200)?}195 }: {<Pallet<T>>::transfer_from(&collection, &spender, &sender, &receiver, item, 200, &Unlimited)?}196196197 // Both source account and token is destroyed197 // Both source account and token is destroyed198 burn_from {198 burn_from {202 };202 };203 let item = create_max_item(&collection, &owner, [(sender.clone(), 200)])?;203 let item = create_max_item(&collection, &owner, [(sender.clone(), 200)])?;204 <Pallet<T>>::set_allowance(&collection, &sender, &burner, item, 200)?;204 <Pallet<T>>::set_allowance(&collection, &sender, &burner, item, 200)?;205 }: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, 200)?}205 }: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, 200, &Unlimited)?}206206207 set_variable_metadata {207 set_variable_metadata {208 let b in 0..CUSTOM_DATA_LIMIT;208 let b in 0..CUSTOM_DATA_LIMIT;pallets/refungible/src/common.rsdiffbeforeafterboth19use sp_std::collections::btree_map::BTreeMap;19use sp_std::collections::btree_map::BTreeMap;20use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight, BoundedVec};20use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight, BoundedVec};21use up_data_structs::{TokenId, CustomDataLimit, CreateItemExData, CreateRefungibleExData};21use up_data_structs::{22 TokenId, CustomDataLimit, CreateItemExData, CreateRefungibleExData, budget::Budget,23};22use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};24use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};23use sp_runtime::DispatchError;25use sp_runtime::DispatchError;210 to: T::CrossAccountId,212 to: T::CrossAccountId,211 token: TokenId,213 token: TokenId,212 amount: u128,214 amount: u128,215 nesting_budget: &dyn Budget,213 ) -> DispatchResultWithPostInfo {216 ) -> DispatchResultWithPostInfo {214 with_weight(217 with_weight(215 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token, amount),218 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token, amount, nesting_budget),216 <CommonWeights<T>>::transfer_from(),219 <CommonWeights<T>>::transfer_from(),217 )220 )218 }221 }223 from: T::CrossAccountId,226 from: T::CrossAccountId,224 token: TokenId,227 token: TokenId,225 amount: u128,228 amount: u128,229 nesting_budget: &dyn Budget,226 ) -> DispatchResultWithPostInfo {230 ) -> DispatchResultWithPostInfo {227 with_weight(231 with_weight(228 <Pallet<T>>::burn_from(self, &sender, &from, token, amount),232 <Pallet<T>>::burn_from(self, &sender, &from, token, amount, nesting_budget),229 <CommonWeights<T>>::burn_from(),233 <CommonWeights<T>>::burn_from(),230 )234 )231 }235 }pallets/refungible/src/lib.rsdiffbeforeafterboth19use frame_support::{ensure, BoundedVec};19use frame_support::{ensure, BoundedVec};20use up_data_structs::{20use up_data_structs::{21 AccessMode, CollectionId, CustomDataLimit, MAX_REFUNGIBLE_PIECES, TokenId,21 AccessMode, CollectionId, CustomDataLimit, MAX_REFUNGIBLE_PIECES, TokenId,22 CreateCollectionData, CreateRefungibleExData, mapping::TokenAddressMapping,22 CreateCollectionData, CreateRefungibleExData, mapping::TokenAddressMapping, budget::Budget,23};23};24use pallet_evm::account::CrossAccountId;24use pallet_evm::account::CrossAccountId;25use pallet_common::{25use pallet_common::{544 from: &T::CrossAccountId,544 from: &T::CrossAccountId,545 token: TokenId,545 token: TokenId,546 amount: u128,546 amount: u128,547 nesting_budget: &dyn Budget,547 ) -> Result<Option<u128>, DispatchError> {548 ) -> Result<Option<u128>, DispatchError> {548 if spender.conv_eq(from) {549 if spender.conv_eq(from) {549 return Ok(None);550 return Ok(None);555 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {556 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {556 // TODO: should collection owner be allowed to perform this transfer?557 // TODO: should collection owner be allowed to perform this transfer?557 ensure!(558 ensure!(558 <PalletStructure<T>>::indirectly_owned(spender.clone(), source.0, source.1, 1)?,559 <PalletStructure<T>>::indirectly_owned(560 spender.clone(),561 source.0,562 source.1,563 nesting_budget564 )?,559 <CommonError<T>>::ApprovedValueTooLow,565 <CommonError<T>>::ApprovedValueTooLow,560 );566 );578 to: &T::CrossAccountId,584 to: &T::CrossAccountId,579 token: TokenId,585 token: TokenId,580 amount: u128,586 amount: u128,587 nesting_budget: &dyn Budget,581 ) -> DispatchResult {588 ) -> DispatchResult {582 let allowance = Self::check_allowed(collection, spender, from, token, amount)?;589 let allowance =590 Self::check_allowed(collection, spender, from, token, amount, nesting_budget)?;583591584 // =========592 // =========585593596 from: &T::CrossAccountId,604 from: &T::CrossAccountId,597 token: TokenId,605 token: TokenId,598 amount: u128,606 amount: u128,607 nesting_budget: &dyn Budget,599 ) -> DispatchResult {608 ) -> DispatchResult {600 let allowance = Self::check_allowed(collection, spender, from, token, amount)?;609 let allowance =610 Self::check_allowed(collection, spender, from, token, amount, nesting_budget)?;601611602 // =========612 // =========603613pallets/structure/src/lib.rsdiffbeforeafterboth6use frame_support::fail;6use frame_support::fail;7pub use pallet::*;7pub use pallet::*;8use pallet_common::{dispatch::CollectionDispatch, CollectionHandle};8use pallet_common::{dispatch::CollectionDispatch, CollectionHandle};9use up_data_structs::{CollectionId, TokenId, mapping::TokenAddressMapping};9use up_data_structs::{CollectionId, TokenId, mapping::TokenAddressMapping, budget::Budget};1011#[cfg(feature = "runtime-benchmarks")]12pub mod benchmarking;13pub mod weights;1415pub type SelfWeightOf<T> = <T as crate::Config>::WeightInfo;101611#[frame_support::pallet]17#[frame_support::pallet]12pub mod pallet {18pub mod pallet {354136 #[pallet::config]42 #[pallet::config]37 pub trait Config: frame_system::Config + pallet_common::Config {43 pub trait Config: frame_system::Config + pallet_common::Config {44 type WeightInfo: weights::WeightInfo;38 type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;45 type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;39 type Call: Parameter + UnfilteredDispatchable<Origin = Self::Origin> + GetDispatchInfo;46 type Call: Parameter + UnfilteredDispatchable<Origin = Self::Origin> + GetDispatchInfo;40 }47 }127 pub fn find_topmost_owner(134 pub fn find_topmost_owner(128 collection: CollectionId,135 collection: CollectionId,129 token: TokenId,136 token: TokenId,130 max_depth: u32,137 budget: &dyn Budget,131 ) -> Result<T::CrossAccountId, DispatchError> {138 ) -> Result<T::CrossAccountId, DispatchError> {132 let owner = Self::parent_chain(collection, token)139 let owner = Self::parent_chain(collection, token)133 .take(max_depth as usize)140 .take_while(|_| budget.consume())134 .find(|p| matches!(p, Ok(Parent::Normal(_) | Parent::TokenNotFound)))141 .find(|p| matches!(p, Ok(Parent::Normal(_) | Parent::TokenNotFound)))135 .ok_or(<Error<T>>::DepthLimit)??;142 .ok_or(<Error<T>>::DepthLimit)??;136143145 user: T::CrossAccountId,152 user: T::CrossAccountId,146 collection: CollectionId,153 collection: CollectionId,147 token: TokenId,154 token: TokenId,148 max_depth: u32,155 budget: &dyn Budget,149 ) -> Result<bool, DispatchError> {156 ) -> Result<bool, DispatchError> {150 let target_parent = match T::CrossTokenAddressMapping::address_to_token(&user) {157 let target_parent = match T::CrossTokenAddressMapping::address_to_token(&user) {151 Some((collection, token)) => Parent::Token(collection, token),158 Some((collection, token)) => Parent::Token(collection, token),152 None => Parent::Normal(user),159 None => Parent::Normal(user),153 };160 };154161155 Ok(Self::parent_chain(collection, token)162 Ok(Self::parent_chain(collection, token)156 .take(max_depth as usize)163 .take_while(|_| budget.consume())157 .any(|parent| Ok(&target_parent) == parent.as_ref()))164 .any(|parent| Ok(&target_parent) == parent.as_ref()))158 }165 }159}166}pallets/unique/src/benchmarking.rsdiffbeforeafterboth19use super::*;19use super::*;20use crate::Pallet;20use crate::Pallet;21use frame_system::RawOrigin;21use frame_system::RawOrigin;22use frame_benchmarking::{benchmarks, account};22use frame_support::traits::{tokens::currency::Currency, Get};23use up_data_structs::*;23use frame_benchmarking::{benchmarks, account};24use sp_runtime::DispatchError;24use sp_runtime::DispatchError;25use pallet_common::benchmarking::{create_data, create_var_data, create_u16_data};25use pallet_common::benchmarking::{create_data, create_var_data, create_u16_data};2626173 owner_can_transfer: Some(true),173 owner_can_transfer: Some(true),174 sponsored_data_rate_limit: None,174 sponsored_data_rate_limit: None,175 transfers_enabled: Some(true),175 transfers_enabled: Some(true),176 nesting_rule: None,176 };177 };177 }: set_collection_limits(RawOrigin::Signed(caller.clone()), collection, cl)178 }: set_collection_limits(RawOrigin::Signed(caller.clone()), collection, cl)178179pallets/unique/src/lib.rsdiffbeforeafterboth43 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,43 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,44 AccessMode, CreateItemData, CollectionLimits, CollectionId, CollectionMode, TokenId,44 AccessMode, CreateItemData, CollectionLimits, CollectionId, CollectionMode, TokenId,45 SchemaVersion, SponsorshipState, MetaUpdatePermission, CreateCollectionData, CustomDataLimit,45 SchemaVersion, SponsorshipState, MetaUpdatePermission, CreateCollectionData, CustomDataLimit,46 CreateItemExData,46 CreateItemExData, budget,47};47};48use pallet_evm::account::CrossAccountId;48use pallet_evm::account::CrossAccountId;49use pallet_common::{49use pallet_common::{807 #[transactional]807 #[transactional]808 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {808 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {809 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);809 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);810 let budget = budget::Value::new(2);810811811 dispatch_call::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value))812 dispatch_call::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))812 }813 }813814814 /// Change ownership of the token.815 /// Change ownership of the token.888 #[transactional]889 #[transactional]889 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {890 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {890 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);891 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);892 let budget = budget::Value::new(2);891893892 dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value))894 dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))893 }895 }894896895 /// Set off-chain data schema.897 /// Set off-chain data schema.primitives/data-structs/src/budget.rsdiffbeforeafterbothno changes
primitives/data-structs/src/lib.rsdiffbeforeafterboth35use scale_info::TypeInfo;35use scale_info::TypeInfo;363637mod bounded;37mod bounded;38pub mod budget;38pub mod mapping;39pub mod mapping;39mod migration;40mod migration;4041