difftreelog
fix forbid non-1 tokenid in native fungibles (#1015)
in: master
* fix: native fungibles collection * refactor: move FungibleItemsHaveNoId to pallet-common
6 files changed
pallets/balances-adapter/src/common.rsdiffbeforeafterboth--- a/pallets/balances-adapter/src/common.rs
+++ b/pallets/balances-adapter/src/common.rs
@@ -1,9 +1,9 @@
use alloc::{vec, vec::Vec};
use core::marker::PhantomData;
-use frame_support::{fail, weights::Weight};
+use frame_support::{ensure, fail, weights::Weight};
use pallet_balances::{weights::SubstrateWeight as BalancesWeight, WeightInfo};
-use pallet_common::{CommonCollectionOperations, CommonWeightInfo};
+use pallet_common::{CommonCollectionOperations, CommonWeightInfo, Error as CommonError};
use up_data_structs::TokenId;
use crate::{Config, NativeFungibleHandle, Pallet};
@@ -77,7 +77,7 @@
_data: up_data_structs::CreateItemData,
_nesting_budget: &dyn up_data_structs::budget::Budget,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn create_multiple_items(
@@ -87,7 +87,7 @@
_data: Vec<up_data_structs::CreateItemData>,
_nesting_budget: &dyn up_data_structs::budget::Budget,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn create_multiple_items_ex(
@@ -96,7 +96,7 @@
_data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,
_nesting_budget: &dyn up_data_structs::budget::Budget,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn burn_item(
@@ -105,7 +105,7 @@
_token: TokenId,
_amount: u128,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn set_collection_properties(
@@ -113,7 +113,7 @@
_sender: <T>::CrossAccountId,
_properties: Vec<up_data_structs::Property>,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn delete_collection_properties(
@@ -121,7 +121,7 @@
_sender: &<T>::CrossAccountId,
_property_keys: Vec<up_data_structs::PropertyKey>,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn set_token_properties(
@@ -131,7 +131,7 @@
_properties: Vec<up_data_structs::Property>,
_budget: &dyn up_data_structs::budget::Budget,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn delete_token_properties(
@@ -141,7 +141,7 @@
_property_keys: Vec<up_data_structs::PropertyKey>,
_budget: &dyn up_data_structs::budget::Budget,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn get_token_properties_raw(
@@ -161,18 +161,23 @@
_sender: &<T>::CrossAccountId,
_property_permissions: Vec<up_data_structs::PropertyKeyPermission>,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn transfer(
&self,
sender: <T>::CrossAccountId,
to: <T>::CrossAccountId,
- _token: TokenId,
+ token: TokenId,
amount: u128,
- budget: &dyn up_data_structs::budget::Budget,
+ _budget: &dyn up_data_structs::budget::Budget,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- <Pallet<T>>::transfer(self, &sender, &to, amount, budget)
+ ensure!(
+ token == TokenId::default(),
+ <CommonError<T>>::FungibleItemsHaveNoId
+ );
+
+ <Pallet<T>>::transfer(&sender, &to, amount)
}
fn approve(
@@ -182,7 +187,7 @@
_token: TokenId,
_amount: u128,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn approve_from(
@@ -193,7 +198,7 @@
_token: TokenId,
_amount: u128,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn transfer_from(
@@ -201,11 +206,16 @@
sender: <T>::CrossAccountId,
from: <T>::CrossAccountId,
to: <T>::CrossAccountId,
- _token: TokenId,
+ token: TokenId,
amount: u128,
budget: &dyn up_data_structs::budget::Budget,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- <Pallet<T>>::transfer_from(self, &sender, &from, &to, amount, budget)
+ ensure!(
+ token == TokenId::default(),
+ <CommonError<T>>::FungibleItemsHaveNoId
+ );
+
+ <Pallet<T>>::transfer_from(&sender, &from, &to, amount, budget)
}
fn burn_from(
@@ -216,7 +226,7 @@
_amount: u128,
_budget: &dyn up_data_structs::budget::Budget,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn check_nesting(
@@ -226,7 +236,7 @@
_under: TokenId,
_budget: &dyn up_data_structs::budget::Budget,
) -> frame_support::sp_runtime::DispatchResult {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn nest(&self, _under: TokenId, _to_nest: (up_data_structs::CollectionId, TokenId)) {}
@@ -332,7 +342,7 @@
_operator: <T>::CrossAccountId,
_approve: bool,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
fn allowance_for_all(
@@ -347,6 +357,6 @@
&self,
_token: TokenId,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- fail!(<pallet_common::Error<T>>::UnsupportedOperation);
+ fail!(<CommonError<T>>::UnsupportedOperation);
}
}
pallets/balances-adapter/src/erc.rsdiffbeforeafterboth1use evm_coder::{abi::AbiType, generate_stubgen, solidity_interface, types::*};2use pallet_balances::WeightInfo;3use pallet_common::{4 erc::{CommonEvmHandler, CrossAccountId, PrecompileHandle, PrecompileResult},5 eth::CrossAddress,6};7use pallet_evm_coder_substrate::{8 call, dispatch_to_evm,9 execution::{PreDispatch, Result},10 frontier_contract, WithRecorder,11};12use pallet_structure::{weights::WeightInfo as _, SelfWeightOf as StructureWeight};13use sp_core::{Get, U256};1415use crate::{Config, NativeFungibleHandle, Pallet, SelfWeightOf};1617frontier_contract! {18 macro_rules! NativeFungibleHandle_result {...}19 impl<T: Config> Contract for NativeFungibleHandle<T> {...}20}2122#[solidity_interface(name = ERC20, enum(derive(PreDispatch)), enum_attr(weight), expect_selector = 0x942e8b22)]23impl<T: Config> NativeFungibleHandle<T> {24 fn allowance(&self, _owner: Address, _spender: Address) -> Result<U256> {25 Ok(U256::zero())26 }2728 fn approve(&mut self, _caller: Caller, _spender: Address, _amount: U256) -> Result<bool> {29 Err("approve not supported".into())30 }3132 fn balance_of(&self, owner: Address) -> Result<U256> {33 self.consume_store_reads(1)?;34 let owner = T::CrossAccountId::from_eth(owner);35 let balance = <Pallet<T>>::balance_of(&owner);36 Ok(balance.into())37 }3839 fn decimals(&self) -> Result<u8> {40 Ok(T::Decimals::get())41 }4243 fn name(&self) -> Result<String> {44 Ok(T::Name::get())45 }4647 fn symbol(&self) -> Result<String> {48 Ok(T::Symbol::get())49 }5051 fn total_supply(&self) -> Result<U256> {52 self.consume_store_reads(1)?;53 Ok(<Pallet<T>>::total_issuance().into())54 }5556 #[weight(<SelfWeightOf<T>>::transfer_allow_death())]57 fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {58 let caller = T::CrossAccountId::from_eth(caller);59 let to = T::CrossAccountId::from_eth(to);60 let amount = amount.try_into().map_err(|_| "amount overflow")?;61 let budget = self62 .recorder()63 .weight_calls_budget(<StructureWeight<T>>::find_parent());6465 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget)66 .map_err(|e| dispatch_to_evm::<T>(e.error))?;67 Ok(true)68 }6970 #[weight(<SelfWeightOf<T>>::transfer_allow_death())]71 fn transfer_from(72 &mut self,73 caller: Caller,74 from: Address,75 to: Address,76 amount: U256,77 ) -> Result<bool> {78 let caller = T::CrossAccountId::from_eth(caller);79 let from = T::CrossAccountId::from_eth(from);80 let to = T::CrossAccountId::from_eth(to);81 let amount = amount.try_into().map_err(|_| "amount overflow")?;82 let budget = self83 .recorder()84 .weight_calls_budget(<StructureWeight<T>>::find_parent());8586 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)87 .map_err(|e| dispatch_to_evm::<T>(e.error))?;88 Ok(true)89 }90}9192#[solidity_interface(name = ERC20UniqueExtensions, enum(derive(PreDispatch)), enum_attr(weight))]93impl<T: Config> NativeFungibleHandle<T>94where95 T::AccountId: From<[u8; 32]>,96{97 fn balance_of_cross(&self, owner: CrossAddress) -> Result<U256> {98 self.consume_store_reads(1)?;99 let owner = owner.into_sub_cross_account::<T>()?;100 let balance = <Pallet<T>>::balance_of(&owner);101 Ok(balance.into())102 }103104 #[weight(<SelfWeightOf<T>>::transfer_allow_death())]105 fn transfer_cross(&mut self, caller: Caller, to: CrossAddress, amount: U256) -> Result<bool> {106 let caller = T::CrossAccountId::from_eth(caller);107 let to = to.into_sub_cross_account::<T>()?;108 let amount = amount.try_into().map_err(|_| "amount overflow")?;109 let budget = self110 .recorder()111 .weight_calls_budget(<StructureWeight<T>>::find_parent());112113 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget)114 .map_err(|e| dispatch_to_evm::<T>(e.error))?;115116 Ok(true)117 }118119 #[weight(<SelfWeightOf<T>>::transfer_allow_death())]120 fn transfer_from_cross(121 &mut self,122 caller: Caller,123 from: CrossAddress,124 to: CrossAddress,125 amount: U256,126 ) -> Result<bool> {127 let caller = T::CrossAccountId::from_eth(caller);128 let from = from.into_sub_cross_account::<T>()?;129 let to = to.into_sub_cross_account::<T>()?;130 let amount = amount.try_into().map_err(|_| "amount overflow")?;131132 if from != caller {133 return Err("no permission".into());134 }135136 let budget = self137 .recorder()138 .weight_calls_budget(<StructureWeight<T>>::find_parent());139140 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)141 .map_err(|e| dispatch_to_evm::<T>(e.error))?;142143 Ok(true)144 }145}146147#[solidity_interface(148 name = UniqueNativeFungible,149 is(ERC20, ERC20UniqueExtensions),150 enum(derive(PreDispatch))151)]152impl<T: Config> NativeFungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}153154generate_stubgen!(gen_impl, UniqueNativeFungibleCall<()>, true);155generate_stubgen!(gen_iface, UniqueNativeFungibleCall<()>, false);156157impl<T: Config> CommonEvmHandler for NativeFungibleHandle<T>158where159 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,160{161 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueNativeFungible.raw");162163 fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {164 call::<T, UniqueNativeFungibleCall<T>, _, _>(handle, self)165 }166}pallets/balances-adapter/src/lib.rsdiffbeforeafterboth--- a/pallets/balances-adapter/src/lib.rs
+++ b/pallets/balances-adapter/src/lib.rs
@@ -155,20 +155,15 @@
Ok(Self::balance_of(from))
}
- /// Transfers the specified amount of tokens. Will check that
- /// the transfer is allowed for the token.
+ /// Transfers the specified amount of tokens.
///
- /// - `collection`: Collection that contains the token.
/// - `from`: Owner of tokens to transfer.
/// - `to`: Recepient of transfered tokens.
/// - `amount`: Amount of tokens to transfer.
- /// - `nesting_budget`: Limit for searching parents in-depth to check ownership.
pub fn transfer(
- _collection: &NativeFungibleHandle<T>,
from: &T::CrossAccountId,
to: &T::CrossAccountId,
amount: u128,
- _nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
<PalletCommon<T>>::ensure_correct_receiver(to)?;
@@ -185,19 +180,18 @@
})
}
- /// Transfer NFT token from one account to another.
+ /// Transfer tokens from one account to another.
///
- /// Same as the [`Self::transfer`] but spender doesn't needs to be the owner of the token.
- /// The owner should set allowance for the spender to transfer token.
+ /// Same as the [`Self::transfer`] but the spender doesn't needs to be the direct owner of the token.
+ /// The spender must be allowed to transfer token.
+ /// If the tokens are nested in an NFT and the spender owns the NFT, the allowance is considered to be set.
///
- /// - `collection`: Collection that contains the token.
/// - `spender`: Account that spend the money.
/// - `from`: Owner of tokens to transfer.
/// - `to`: Recepient of transfered tokens.
/// - `amount`: Amount of tokens to transfer.
/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.
pub fn transfer_from(
- collection: &NativeFungibleHandle<T>,
spender: &T::CrossAccountId,
from: &T::CrossAccountId,
to: &T::CrossAccountId,
@@ -208,7 +202,7 @@
if allowance < amount {
return Err(<CommonError<T>>::ApprovedValueTooLow.into());
}
- Self::transfer(collection, from, to, amount, nesting_budget)
+ Self::transfer(from, to, amount)
}
}
}
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -783,6 +783,9 @@
/// The user is not an administrator.
UserIsNotCollectionAdmin,
+
+ /// Fungible tokens hold no ID, and the default value of TokenId for a fungible collection is 0.
+ FungibleItemsHaveNoId,
}
/// Storage of the count of created collections. Essentially contains the last collection ID.
pallets/fungible/src/common.rsdiffbeforeafterboth--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -19,7 +19,7 @@
use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};
use pallet_common::{
weights::WeightInfo as _, with_weight, CommonCollectionOperations, CommonWeightInfo,
- RefungibleExtensions, SelfWeightOf as PalletCommonWeightOf,
+ Error as CommonError, RefungibleExtensions, SelfWeightOf as PalletCommonWeightOf,
};
use sp_runtime::{ArithmeticError, DispatchError};
use sp_std::{vec, vec::Vec};
@@ -169,7 +169,7 @@
) -> DispatchResultWithPostInfo {
ensure!(
token == TokenId::default(),
- <Error<T>>::FungibleItemsHaveNoId
+ <CommonError<T>>::FungibleItemsHaveNoId
);
with_weight(
@@ -188,7 +188,7 @@
) -> DispatchResultWithPostInfo {
ensure!(
token == TokenId::default(),
- <Error<T>>::FungibleItemsHaveNoId
+ <CommonError<T>>::FungibleItemsHaveNoId
);
<Pallet<T>>::transfer(self, &from, &to, amount, nesting_budget)
@@ -203,7 +203,7 @@
) -> DispatchResultWithPostInfo {
ensure!(
token == TokenId::default(),
- <Error<T>>::FungibleItemsHaveNoId
+ <CommonError<T>>::FungibleItemsHaveNoId
);
with_weight(
@@ -222,7 +222,7 @@
) -> DispatchResultWithPostInfo {
ensure!(
token == TokenId::default(),
- <Error<T>>::FungibleItemsHaveNoId
+ <CommonError<T>>::FungibleItemsHaveNoId
);
with_weight(
@@ -242,7 +242,7 @@
) -> DispatchResultWithPostInfo {
ensure!(
token == TokenId::default(),
- <Error<T>>::FungibleItemsHaveNoId
+ <CommonError<T>>::FungibleItemsHaveNoId
);
<Pallet<T>>::transfer_from(self, &sender, &from, &to, amount, nesting_budget)
@@ -258,7 +258,7 @@
) -> DispatchResultWithPostInfo {
ensure!(
token == TokenId::default(),
- <Error<T>>::FungibleItemsHaveNoId
+ <CommonError<T>>::FungibleItemsHaveNoId
);
with_weight(
pallets/fungible/src/lib.rsdiffbeforeafterboth--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -123,8 +123,6 @@
pub enum Error<T> {
/// Not Fungible item data used to mint in Fungible collection.
NotFungibleDataUsedToMintFungibleCollectionToken,
- /// Fungible tokens hold no ID, and the default value of TokenId for Fungible collection is 0.
- FungibleItemsHaveNoId,
/// Tried to set data for fungible item.
FungibleItemsDontHaveData,
/// Fungible token does not support nesting.