difftreelog
feat(weight) Changed weight calculation system for transfer & transfer_from (FT)
in: master
9 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6558,7 +6558,7 @@
[[package]]
name = "pallet-fungible"
-version = "0.1.10"
+version = "0.1.11"
dependencies = [
"evm-coder",
"frame-benchmarking",
pallets/foreign-assets/src/impl_fungibles.rsdiffbeforeafterboth--- 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)
}
pallets/fungible/CHANGELOG.mddiffbeforeafterboth--- a/pallets/fungible/CHANGELOG.md
+++ b/pallets/fungible/CHANGELOG.md
@@ -4,6 +4,12 @@
<!-- bureaucrate goes here -->
+## [0.1.11] - 2023-03-28
+
+### Fixed
+
+- The weight of `transfer` and `transfer_from`.
+
## [0.1.10] - 2023-02-01
### Added
pallets/fungible/Cargo.tomldiffbeforeafterboth--- 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.
pallets/fungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/fungible/src/benchmarking.rs
+++ b/pallets/fungible/src/benchmarking.rs
@@ -92,14 +92,22 @@
<Pallet<T>>::create_item(&collection, &owner, (owner_eth.clone(), 200), &Unlimited)?;
}: {<Pallet<T>>::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;
};
<Pallet<T>>::create_item(&collection, &owner, (sender.clone(), 200), &Unlimited)?;
<Pallet<T>>::set_allowance(&collection, &sender, &spender, 200)?;
- }: {<Pallet<T>>::transfer_from(&collection, &spender, &sender, &receiver, 100, &Unlimited)?}
+ }: {<Pallet<T>>::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;
+ };
+ <Pallet<T>>::create_item(&collection, &owner, (sender.clone(), 200), &Unlimited)?;
+ }: {<Pallet<T>>::set_allowance_unchecked(&collection, &sender, &spender, 200);}
burn_from {
bench_init!{
pallets/fungible/src/common.rsdiffbeforeafterboth--- 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 {
- <SelfWeightOf<T>>::transfer()
+ <SelfWeightOf<T>>::transfer() + <PalletCommonWeightOf<T>>::check_accesslist() * 2
}
fn approve() -> Weight {
@@ -90,7 +90,9 @@
}
fn transfer_from() -> Weight {
- <SelfWeightOf<T>>::transfer_from()
+ <SelfWeightOf<T>>::transfer()
+ + <SelfWeightOf<T>>::check_allowed_raw()
+ + <SelfWeightOf<T>>::set_allowance_unchecked_raw()
}
fn burn_from() -> Weight {
@@ -232,10 +234,7 @@
<Error<T>>::FungibleItemsHaveNoId
);
- with_weight(
- <Pallet<T>>::transfer(self, &from, &to, amount, nesting_budget),
- <CommonWeights<T>>::transfer(),
- )
+ <Pallet<T>>::transfer(self, &from, &to, amount, nesting_budget)
}
fn approve(
@@ -289,10 +288,7 @@
<Error<T>>::FungibleItemsHaveNoId
);
- with_weight(
- <Pallet<T>>::transfer_from(self, &sender, &from, &to, amount, nesting_budget),
- <CommonWeights<T>>::transfer_from(),
- )
+ <Pallet<T>>::transfer_from(self, &sender, &from, &to, amount, nesting_budget)
}
fn burn_from(
pallets/fungible/src/erc.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//! ERC-20 standart support implementation.1819extern crate alloc;20use core::char::{REPLACEMENT_CHARACTER, decode_utf16};21use core::convert::TryInto;22use evm_coder::AbiCoder;23use evm_coder::{abi::AbiType, ToLog, generate_stubgen, solidity_interface, types::*};24use up_data_structs::CollectionMode;25use pallet_common::{26 CollectionHandle,27 erc::{CommonEvmHandler, PrecompileResult, CollectionCall},28 eth::CrossAddress,29};30use sp_std::vec::Vec;31use pallet_evm::{account::CrossAccountId, PrecompileHandle};32use pallet_evm_coder_substrate::{33 call, dispatch_to_evm,34 execution::{PreDispatch, Result},35 frontier_contract,36};37use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};38use sp_core::{U256, Get};3940use crate::{41 Allowance, Balance, Config, FungibleHandle, Pallet, TotalSupply, SelfWeightOf,42 weights::WeightInfo,43};4445frontier_contract! {46 macro_rules! FungibleHandle_result {...}47 impl<T: Config> Contract for FungibleHandle<T> {...}48}4950#[derive(ToLog)]51pub enum ERC20Events {52 Transfer {53 #[indexed]54 from: Address,55 #[indexed]56 to: Address,57 value: U256,58 },59 Approval {60 #[indexed]61 owner: Address,62 #[indexed]63 spender: Address,64 value: U256,65 },66}6768#[derive(AbiCoder, Debug)]69pub struct AmountForAddress {70 to: Address,71 amount: U256,72}7374#[solidity_interface(name = ERC20, events(ERC20Events), enum(derive(PreDispatch)), enum_attr(weight), expect_selector = 0x942e8b22)]75impl<T: Config> FungibleHandle<T> {76 fn name(&self) -> Result<String> {77 Ok(decode_utf16(self.name.iter().copied())78 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))79 .collect::<String>())80 }81 fn symbol(&self) -> Result<String> {82 Ok(String::from_utf8_lossy(&self.token_prefix).into())83 }84 fn total_supply(&self) -> Result<U256> {85 self.consume_store_reads(1)?;86 Ok(<TotalSupply<T>>::get(self.id).into())87 }8889 fn decimals(&self) -> Result<u8> {90 Ok(if let CollectionMode::Fungible(decimals) = &self.mode {91 *decimals92 } else {93 unreachable!()94 })95 }96 fn balance_of(&self, owner: Address) -> Result<U256> {97 self.consume_store_reads(1)?;98 let owner = T::CrossAccountId::from_eth(owner);99 let balance = <Balance<T>>::get((self.id, owner));100 Ok(balance.into())101 }102 #[weight(<SelfWeightOf<T>>::transfer())]103 fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {104 let caller = T::CrossAccountId::from_eth(caller);105 let to = T::CrossAccountId::from_eth(to);106 let amount = amount.try_into().map_err(|_| "amount overflow")?;107 let budget = self108 .recorder109 .weight_calls_budget(<StructureWeight<T>>::find_parent());110111 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;112 Ok(true)113 }114115 #[weight(<SelfWeightOf<T>>::transfer_from())]116 fn transfer_from(117 &mut self,118 caller: Caller,119 from: Address,120 to: Address,121 amount: U256,122 ) -> Result<bool> {123 let caller = T::CrossAccountId::from_eth(caller);124 let from = T::CrossAccountId::from_eth(from);125 let to = T::CrossAccountId::from_eth(to);126 let amount = amount.try_into().map_err(|_| "amount overflow")?;127 let budget = self128 .recorder129 .weight_calls_budget(<StructureWeight<T>>::find_parent());130131 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)132 .map_err(dispatch_to_evm::<T>)?;133 Ok(true)134 }135 #[weight(<SelfWeightOf<T>>::approve())]136 fn approve(&mut self, caller: Caller, spender: Address, amount: U256) -> Result<bool> {137 let caller = T::CrossAccountId::from_eth(caller);138 let spender = T::CrossAccountId::from_eth(spender);139 let amount = amount.try_into().map_err(|_| "amount overflow")?;140141 <Pallet<T>>::set_allowance(self, &caller, &spender, amount)142 .map_err(dispatch_to_evm::<T>)?;143 Ok(true)144 }145 fn allowance(&self, owner: Address, spender: Address) -> Result<U256> {146 self.consume_store_reads(1)?;147 let owner = T::CrossAccountId::from_eth(owner);148 let spender = T::CrossAccountId::from_eth(spender);149150 Ok(<Allowance<T>>::get((self.id, owner, spender)).into())151 }152}153154#[solidity_interface(name = ERC20Mintable, enum(derive(PreDispatch)), enum_attr(weight))]155impl<T: Config> FungibleHandle<T> {156 /// Mint tokens for `to` account.157 /// @param to account that will receive minted tokens158 /// @param amount amount of tokens to mint159 #[weight(<SelfWeightOf<T>>::create_item())]160 fn mint(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {161 let caller = T::CrossAccountId::from_eth(caller);162 let to = T::CrossAccountId::from_eth(to);163 let amount = amount.try_into().map_err(|_| "amount overflow")?;164 let budget = self165 .recorder166 .weight_calls_budget(<StructureWeight<T>>::find_parent());167 <Pallet<T>>::create_item(self, &caller, (to, amount), &budget)168 .map_err(dispatch_to_evm::<T>)?;169 Ok(true)170 }171}172173#[solidity_interface(name = ERC20UniqueExtensions, enum(derive(PreDispatch)), enum_attr(weight))]174impl<T: Config> FungibleHandle<T>175where176 T::AccountId: From<[u8; 32]>,177{178 /// @dev Function to check the amount of tokens that an owner allowed to a spender.179 /// @param owner crossAddress The address which owns the funds.180 /// @param spender crossAddress The address which will spend the funds.181 /// @return A uint256 specifying the amount of tokens still available for the spender.182 fn allowance_cross(&self, owner: CrossAddress, spender: CrossAddress) -> Result<U256> {183 let owner = owner.into_sub_cross_account::<T>()?;184 let spender = spender.into_sub_cross_account::<T>()?;185186 Ok(<Allowance<T>>::get((self.id, owner, spender)).into())187 }188189 /// @notice A description for the collection.190 fn description(&self) -> String {191 decode_utf16(self.description.iter().copied())192 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))193 .collect::<String>()194 }195196 #[weight(<SelfWeightOf<T>>::create_item())]197 fn mint_cross(&mut self, caller: Caller, to: CrossAddress, amount: U256) -> Result<bool> {198 let caller = T::CrossAccountId::from_eth(caller);199 let to = to.into_sub_cross_account::<T>()?;200 let amount = amount.try_into().map_err(|_| "amount overflow")?;201 let budget = self202 .recorder203 .weight_calls_budget(<StructureWeight<T>>::find_parent());204 <Pallet<T>>::create_item(&self, &caller, (to, amount), &budget)205 .map_err(dispatch_to_evm::<T>)?;206 Ok(true)207 }208209 #[weight(<SelfWeightOf<T>>::approve())]210 fn approve_cross(211 &mut self,212 caller: Caller,213 spender: CrossAddress,214 amount: U256,215 ) -> Result<bool> {216 let caller = T::CrossAccountId::from_eth(caller);217 let spender = spender.into_sub_cross_account::<T>()?;218 let amount = amount.try_into().map_err(|_| "amount overflow")?;219220 <Pallet<T>>::set_allowance(self, &caller, &spender, amount)221 .map_err(dispatch_to_evm::<T>)?;222 Ok(true)223 }224225 /// Burn tokens from account226 /// @dev Function that burns an `amount` of the tokens of a given account,227 /// deducting from the sender's allowance for said account.228 /// @param from The account whose tokens will be burnt.229 /// @param amount The amount that will be burnt.230 #[solidity(hide)]231 #[weight(<SelfWeightOf<T>>::burn_from())]232 fn burn_from(&mut self, caller: Caller, from: Address, amount: U256) -> Result<bool> {233 let caller = T::CrossAccountId::from_eth(caller);234 let from = T::CrossAccountId::from_eth(from);235 let amount = amount.try_into().map_err(|_| "amount overflow")?;236 let budget = self237 .recorder238 .weight_calls_budget(<StructureWeight<T>>::find_parent());239240 <Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)241 .map_err(dispatch_to_evm::<T>)?;242 Ok(true)243 }244245 /// Burn tokens from account246 /// @dev Function that burns an `amount` of the tokens of a given account,247 /// deducting from the sender's allowance for said account.248 /// @param from The account whose tokens will be burnt.249 /// @param amount The amount that will be burnt.250 #[weight(<SelfWeightOf<T>>::burn_from())]251 fn burn_from_cross(252 &mut self,253 caller: Caller,254 from: CrossAddress,255 amount: U256,256 ) -> Result<bool> {257 let caller = T::CrossAccountId::from_eth(caller);258 let from = from.into_sub_cross_account::<T>()?;259 let amount = amount.try_into().map_err(|_| "amount overflow")?;260 let budget = self261 .recorder262 .weight_calls_budget(<StructureWeight<T>>::find_parent());263264 <Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)265 .map_err(dispatch_to_evm::<T>)?;266 Ok(true)267 }268269 /// Mint tokens for multiple accounts.270 /// @param amounts array of pairs of account address and amount271 #[weight(<SelfWeightOf<T>>::create_multiple_items_ex(amounts.len() as u32))]272 fn mint_bulk(&mut self, caller: Caller, amounts: Vec<AmountForAddress>) -> Result<bool> {273 let caller = T::CrossAccountId::from_eth(caller);274 let budget = self275 .recorder276 .weight_calls_budget(<StructureWeight<T>>::find_parent());277 let amounts = amounts278 .into_iter()279 .map(|AmountForAddress { to, amount }| {280 Ok((281 T::CrossAccountId::from_eth(to),282 amount.try_into().map_err(|_| "amount overflow")?,283 ))284 })285 .collect::<Result<_>>()?;286287 <Pallet<T>>::create_multiple_items(self, &caller, amounts, &budget)288 .map_err(dispatch_to_evm::<T>)?;289 Ok(true)290 }291292 #[weight(<SelfWeightOf<T>>::transfer())]293 fn transfer_cross(&mut self, caller: Caller, to: CrossAddress, amount: U256) -> Result<bool> {294 let caller = T::CrossAccountId::from_eth(caller);295 let to = to.into_sub_cross_account::<T>()?;296 let amount = amount.try_into().map_err(|_| "amount overflow")?;297 let budget = self298 .recorder299 .weight_calls_budget(<StructureWeight<T>>::find_parent());300301 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;302 Ok(true)303 }304305 #[weight(<SelfWeightOf<T>>::transfer_from())]306 fn transfer_from_cross(307 &mut self,308 caller: Caller,309 from: CrossAddress,310 to: CrossAddress,311 amount: U256,312 ) -> Result<bool> {313 let caller = T::CrossAccountId::from_eth(caller);314 let from = from.into_sub_cross_account::<T>()?;315 let to = to.into_sub_cross_account::<T>()?;316 let amount = amount.try_into().map_err(|_| "amount overflow")?;317 let budget = self318 .recorder319 .weight_calls_budget(<StructureWeight<T>>::find_parent());320321 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)322 .map_err(dispatch_to_evm::<T>)?;323 Ok(true)324 }325326 /// @notice Returns collection helper contract address327 fn collection_helper_address(&self) -> Result<Address> {328 Ok(T::ContractAddress::get())329 }330331 /// @notice Balance of account332 /// @param owner An cross address for whom to query the balance333 /// @return The number of fingibles owned by `owner`, possibly zero334 fn balance_of_cross(&self, owner: CrossAddress) -> Result<U256> {335 self.consume_store_reads(1)?;336 let balance = <Balance<T>>::get((self.id, owner.into_sub_cross_account::<T>()?));337 Ok(balance.into())338 }339}340341#[solidity_interface(342 name = UniqueFungible,343 is(344 ERC20,345 ERC20Mintable,346 ERC20UniqueExtensions,347 Collection(via(common_mut returns CollectionHandle<T>)),348 ),349 enum(derive(PreDispatch))350)]351impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}352353generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true);354generate_stubgen!(gen_iface, UniqueFungibleCall<()>, false);355356impl<T: Config> CommonEvmHandler for FungibleHandle<T>357where358 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,359{360 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");361362 fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {363 call::<T, UniqueFungibleCall<T>, _, _>(handle, self)364 }365}1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! ERC-20 standart support implementation.1819extern crate alloc;20use core::char::{REPLACEMENT_CHARACTER, decode_utf16};21use core::convert::TryInto;22use evm_coder::AbiCoder;23use evm_coder::{abi::AbiType, ToLog, generate_stubgen, solidity_interface, types::*};24use up_data_structs::CollectionMode;25use pallet_common::{26 CollectionHandle,27 erc::{CommonEvmHandler, PrecompileResult, CollectionCall},28 eth::CrossAddress,29 CommonWeightInfo as _,30};31use sp_std::vec::Vec;32use pallet_evm::{account::CrossAccountId, PrecompileHandle};33use pallet_evm_coder_substrate::{34 call, dispatch_to_evm,35 execution::{PreDispatch, Result},36 frontier_contract,37};38use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};39use sp_core::{U256, Get};4041use crate::{42 Allowance, Balance, Config, FungibleHandle, Pallet, TotalSupply, SelfWeightOf,43 weights::WeightInfo, common::CommonWeights,44};4546frontier_contract! {47 macro_rules! FungibleHandle_result {...}48 impl<T: Config> Contract for FungibleHandle<T> {...}49}5051#[derive(ToLog)]52pub enum ERC20Events {53 Transfer {54 #[indexed]55 from: Address,56 #[indexed]57 to: Address,58 value: U256,59 },60 Approval {61 #[indexed]62 owner: Address,63 #[indexed]64 spender: Address,65 value: U256,66 },67}6869#[derive(AbiCoder, Debug)]70pub struct AmountForAddress {71 to: Address,72 amount: U256,73}7475#[solidity_interface(name = ERC20, events(ERC20Events), enum(derive(PreDispatch)), enum_attr(weight), expect_selector = 0x942e8b22)]76impl<T: Config> FungibleHandle<T> {77 fn name(&self) -> Result<String> {78 Ok(decode_utf16(self.name.iter().copied())79 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))80 .collect::<String>())81 }82 fn symbol(&self) -> Result<String> {83 Ok(String::from_utf8_lossy(&self.token_prefix).into())84 }85 fn total_supply(&self) -> Result<U256> {86 self.consume_store_reads(1)?;87 Ok(<TotalSupply<T>>::get(self.id).into())88 }8990 fn decimals(&self) -> Result<u8> {91 Ok(if let CollectionMode::Fungible(decimals) = &self.mode {92 *decimals93 } else {94 unreachable!()95 })96 }97 fn balance_of(&self, owner: Address) -> Result<U256> {98 self.consume_store_reads(1)?;99 let owner = T::CrossAccountId::from_eth(owner);100 let balance = <Balance<T>>::get((self.id, owner));101 Ok(balance.into())102 }103 #[weight(<CommonWeights<T>>::transfer())]104 fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {105 let caller = T::CrossAccountId::from_eth(caller);106 let to = T::CrossAccountId::from_eth(to);107 let amount = amount.try_into().map_err(|_| "amount overflow")?;108 let budget = self109 .recorder110 .weight_calls_budget(<StructureWeight<T>>::find_parent());111112 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;113 Ok(true)114 }115116 #[weight(<CommonWeights<T>>::transfer_from())]117 fn transfer_from(118 &mut self,119 caller: Caller,120 from: Address,121 to: Address,122 amount: U256,123 ) -> Result<bool> {124 let caller = T::CrossAccountId::from_eth(caller);125 let from = T::CrossAccountId::from_eth(from);126 let to = T::CrossAccountId::from_eth(to);127 let amount = amount.try_into().map_err(|_| "amount overflow")?;128 let budget = self129 .recorder130 .weight_calls_budget(<StructureWeight<T>>::find_parent());131132 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)133 .map_err(|e| dispatch_to_evm::<T>(e.error))?;134 Ok(true)135 }136 #[weight(<SelfWeightOf<T>>::approve())]137 fn approve(&mut self, caller: Caller, spender: Address, amount: U256) -> Result<bool> {138 let caller = T::CrossAccountId::from_eth(caller);139 let spender = T::CrossAccountId::from_eth(spender);140 let amount = amount.try_into().map_err(|_| "amount overflow")?;141142 <Pallet<T>>::set_allowance(self, &caller, &spender, amount)143 .map_err(dispatch_to_evm::<T>)?;144 Ok(true)145 }146 fn allowance(&self, owner: Address, spender: Address) -> Result<U256> {147 self.consume_store_reads(1)?;148 let owner = T::CrossAccountId::from_eth(owner);149 let spender = T::CrossAccountId::from_eth(spender);150151 Ok(<Allowance<T>>::get((self.id, owner, spender)).into())152 }153}154155#[solidity_interface(name = ERC20Mintable, enum(derive(PreDispatch)), enum_attr(weight))]156impl<T: Config> FungibleHandle<T> {157 /// Mint tokens for `to` account.158 /// @param to account that will receive minted tokens159 /// @param amount amount of tokens to mint160 #[weight(<SelfWeightOf<T>>::create_item())]161 fn mint(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {162 let caller = T::CrossAccountId::from_eth(caller);163 let to = T::CrossAccountId::from_eth(to);164 let amount = amount.try_into().map_err(|_| "amount overflow")?;165 let budget = self166 .recorder167 .weight_calls_budget(<StructureWeight<T>>::find_parent());168 <Pallet<T>>::create_item(self, &caller, (to, amount), &budget)169 .map_err(dispatch_to_evm::<T>)?;170 Ok(true)171 }172}173174#[solidity_interface(name = ERC20UniqueExtensions, enum(derive(PreDispatch)), enum_attr(weight))]175impl<T: Config> FungibleHandle<T>176where177 T::AccountId: From<[u8; 32]>,178{179 /// @dev Function to check the amount of tokens that an owner allowed to a spender.180 /// @param owner crossAddress The address which owns the funds.181 /// @param spender crossAddress The address which will spend the funds.182 /// @return A uint256 specifying the amount of tokens still available for the spender.183 fn allowance_cross(&self, owner: CrossAddress, spender: CrossAddress) -> Result<U256> {184 let owner = owner.into_sub_cross_account::<T>()?;185 let spender = spender.into_sub_cross_account::<T>()?;186187 Ok(<Allowance<T>>::get((self.id, owner, spender)).into())188 }189190 /// @notice A description for the collection.191 fn description(&self) -> String {192 decode_utf16(self.description.iter().copied())193 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))194 .collect::<String>()195 }196197 #[weight(<SelfWeightOf<T>>::create_item())]198 fn mint_cross(&mut self, caller: Caller, to: CrossAddress, amount: U256) -> Result<bool> {199 let caller = T::CrossAccountId::from_eth(caller);200 let to = to.into_sub_cross_account::<T>()?;201 let amount = amount.try_into().map_err(|_| "amount overflow")?;202 let budget = self203 .recorder204 .weight_calls_budget(<StructureWeight<T>>::find_parent());205 <Pallet<T>>::create_item(self, &caller, (to, amount), &budget)206 .map_err(dispatch_to_evm::<T>)?;207 Ok(true)208 }209210 #[weight(<SelfWeightOf<T>>::approve())]211 fn approve_cross(212 &mut self,213 caller: Caller,214 spender: CrossAddress,215 amount: U256,216 ) -> Result<bool> {217 let caller = T::CrossAccountId::from_eth(caller);218 let spender = spender.into_sub_cross_account::<T>()?;219 let amount = amount.try_into().map_err(|_| "amount overflow")?;220221 <Pallet<T>>::set_allowance(self, &caller, &spender, amount)222 .map_err(dispatch_to_evm::<T>)?;223 Ok(true)224 }225226 /// Burn tokens from account227 /// @dev Function that burns an `amount` of the tokens of a given account,228 /// deducting from the sender's allowance for said account.229 /// @param from The account whose tokens will be burnt.230 /// @param amount The amount that will be burnt.231 #[solidity(hide)]232 #[weight(<SelfWeightOf<T>>::burn_from())]233 fn burn_from(&mut self, caller: Caller, from: Address, amount: U256) -> Result<bool> {234 let caller = T::CrossAccountId::from_eth(caller);235 let from = T::CrossAccountId::from_eth(from);236 let amount = amount.try_into().map_err(|_| "amount overflow")?;237 let budget = self238 .recorder239 .weight_calls_budget(<StructureWeight<T>>::find_parent());240241 <Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)242 .map_err(dispatch_to_evm::<T>)?;243 Ok(true)244 }245246 /// Burn tokens from account247 /// @dev Function that burns an `amount` of the tokens of a given account,248 /// deducting from the sender's allowance for said account.249 /// @param from The account whose tokens will be burnt.250 /// @param amount The amount that will be burnt.251 #[weight(<SelfWeightOf<T>>::burn_from())]252 fn burn_from_cross(253 &mut self,254 caller: Caller,255 from: CrossAddress,256 amount: U256,257 ) -> Result<bool> {258 let caller = T::CrossAccountId::from_eth(caller);259 let from = from.into_sub_cross_account::<T>()?;260 let amount = amount.try_into().map_err(|_| "amount overflow")?;261 let budget = self262 .recorder263 .weight_calls_budget(<StructureWeight<T>>::find_parent());264265 <Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)266 .map_err(dispatch_to_evm::<T>)?;267 Ok(true)268 }269270 /// Mint tokens for multiple accounts.271 /// @param amounts array of pairs of account address and amount272 #[weight(<SelfWeightOf<T>>::create_multiple_items_ex(amounts.len() as u32))]273 fn mint_bulk(&mut self, caller: Caller, amounts: Vec<AmountForAddress>) -> Result<bool> {274 let caller = T::CrossAccountId::from_eth(caller);275 let budget = self276 .recorder277 .weight_calls_budget(<StructureWeight<T>>::find_parent());278 let amounts = amounts279 .into_iter()280 .map(|AmountForAddress { to, amount }| {281 Ok((282 T::CrossAccountId::from_eth(to),283 amount.try_into().map_err(|_| "amount overflow")?,284 ))285 })286 .collect::<Result<_>>()?;287288 <Pallet<T>>::create_multiple_items(self, &caller, amounts, &budget)289 .map_err(dispatch_to_evm::<T>)?;290 Ok(true)291 }292293 #[weight(<CommonWeights<T>>::transfer())]294 fn transfer_cross(&mut self, caller: Caller, to: CrossAddress, amount: U256) -> Result<bool> {295 let caller = T::CrossAccountId::from_eth(caller);296 let to = to.into_sub_cross_account::<T>()?;297 let amount = amount.try_into().map_err(|_| "amount overflow")?;298 let budget = self299 .recorder300 .weight_calls_budget(<StructureWeight<T>>::find_parent());301302 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;303 Ok(true)304 }305306 #[weight(<CommonWeights<T>>::transfer_from())]307 fn transfer_from_cross(308 &mut self,309 caller: Caller,310 from: CrossAddress,311 to: CrossAddress,312 amount: U256,313 ) -> Result<bool> {314 let caller = T::CrossAccountId::from_eth(caller);315 let from = from.into_sub_cross_account::<T>()?;316 let to = to.into_sub_cross_account::<T>()?;317 let amount = amount.try_into().map_err(|_| "amount overflow")?;318 let budget = self319 .recorder320 .weight_calls_budget(<StructureWeight<T>>::find_parent());321322 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)323 .map_err(|e| dispatch_to_evm::<T>(e.error))?;324 Ok(true)325 }326327 /// @notice Returns collection helper contract address328 fn collection_helper_address(&self) -> Result<Address> {329 Ok(T::ContractAddress::get())330 }331332 /// @notice Balance of account333 /// @param owner An cross address for whom to query the balance334 /// @return The number of fingibles owned by `owner`, possibly zero335 fn balance_of_cross(&self, owner: CrossAddress) -> Result<U256> {336 self.consume_store_reads(1)?;337 let balance = <Balance<T>>::get((self.id, owner.into_sub_cross_account::<T>()?));338 Ok(balance.into())339 }340}341342#[solidity_interface(343 name = UniqueFungible,344 is(345 ERC20,346 ERC20Mintable,347 ERC20UniqueExtensions,348 Collection(via(common_mut returns CollectionHandle<T>)),349 ),350 enum(derive(PreDispatch))351)]352impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}353354generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true);355generate_stubgen!(gen_iface, UniqueFungibleCall<()>, false);356357impl<T: Config> CommonEvmHandler for FungibleHandle<T>358where359 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,360{361 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");362363 fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {364 call::<T, UniqueFungibleCall<T>, _, _>(handle, self)365 }366}pallets/fungible/src/lib.rsdiffbeforeafterboth--- 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(),
<CommonError<T>>::TransferNotAllowed,
);
+ let mut actual_weight = <SelfWeightOf<T>>::transfer();
+
if collection.permissions.access() == AccessMode::AllowList {
collection.check_allowlist(from)?;
collection.check_allowlist(to)?;
+ actual_weight += <PalletCommonWeightOf<T>>::check_accesslist() * 2;
}
<PalletCommon<T>>::ensure_correct_receiver(to)?;
-
let balance_from = <Balance<T>>::get((collection.id, from))
.checked_sub(amount)
.ok_or(<CommonError<T>>::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(<TotalSupply<T>>::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<T>,
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, <SelfWeightOf<T>>::check_allowed_raw());
+ result?;
+
if let Some(allowance) = allowance {
Self::set_allowance_unchecked(collection, from, spender, allowance);
+ add_weight_to_post_info(
+ &mut result,
+ <SelfWeightOf<T>>::set_allowance_unchecked_raw(),
+ )
}
- Ok(())
+ result
}
/// Burn fungible tokens from the account.
pallets/fungible/src/weights.rsdiffbeforeafterboth--- a/pallets/fungible/src/weights.rs
+++ b/pallets/fungible/src/weights.rs
@@ -40,7 +40,8 @@
fn transfer() -> 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;
}
@@ -129,19 +130,17 @@
.saturating_add(T::DbWeight::get().reads(1_u64))
.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 Balance (r:2 w:2)
- /// Proof: Fungible Balance (max_values: None, max_size: Some(77), added: 2552, mode: MaxEncodedLen)
- fn transfer_from() -> 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))
+ // Storage: Fungible Allowance (r:1 w:0)
+ fn check_allowed_raw() -> Weight {
+ Weight::from_ref_time(3_550_000 as u64)
+ .saturating_add(T::DbWeight::get().reads(1 as u64))
}
+ // Storage: Fungible Allowance (r:1 w:1)
+ fn set_allowance_unchecked_raw() -> Weight {
+ Weight::from_ref_time(10_682_000 as u64)
+ .saturating_add(T::DbWeight::get().reads(1 as u64))
+ .saturating_add(T::DbWeight::get().writes(1 as 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)
@@ -243,18 +242,16 @@
.saturating_add(RocksDbWeight::get().reads(1_u64))
.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)
- /// 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 {
- // 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))
+ // Storage: Fungible Allowance (r:1 w:0)
+ fn check_allowed_raw() -> Weight {
+ Weight::from_ref_time(3_550_000 as u64)
+ .saturating_add(RocksDbWeight::get().reads(1 as u64))
+ }
+ // Storage: Fungible Allowance (r:1 w:1)
+ fn set_allowance_unchecked_raw() -> Weight {
+ Weight::from_ref_time(10_682_000 as u64)
+ .saturating_add(RocksDbWeight::get().reads(1 as u64))
+ .saturating_add(RocksDbWeight::get().writes(1 as u64))
}
/// Storage: Fungible Allowance (r:1 w:1)
/// Proof: Fungible Allowance (max_values: None, max_size: Some(93), added: 2568, mode: MaxEncodedLen)