difftreelog
feat add nesting
in: master
5 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6264,9 +6264,11 @@
"pallet-evm",
"pallet-evm-coder-substrate",
"pallet-evm-transaction-payment",
+ "pallet-structure",
"parity-scale-codec",
"scale-info",
"sp-core",
+ "sp-runtime",
"sp-std",
"up-data-structs",
]
pallets/balances-adapter/Cargo.tomldiffbeforeafterboth--- a/pallets/balances-adapter/Cargo.toml
+++ b/pallets/balances-adapter/Cargo.toml
@@ -9,7 +9,9 @@
frame-support = { workspace = true }
frame-system = { workspace = true }
pallet-balances = { workspace = true }
+pallet-structure = { workspace = true }
sp-core = { workspace = true }
+sp-runtime = { workspace = true }
sp-std = { workspace = true }
#Parity
pallets/balances-adapter/src/common.rsdiffbeforeafterboth--- a/pallets/balances-adapter/src/common.rs
+++ b/pallets/balances-adapter/src/common.rs
@@ -1,13 +1,9 @@
use alloc::{vec, vec::Vec};
use core::marker::PhantomData;
-use crate::{Config, NativeFungibleHandle};
-use frame_support::{
- fail,
- traits::{Currency, ExistenceRequirement},
- weights::Weight,
-};
+use crate::{Config, NativeFungibleHandle, Pallet};
+use frame_support::{fail, traits::Currency, weights::Weight};
use pallet_balances::{weights::SubstrateWeight as BalancesWeight, WeightInfo};
-use pallet_common::{erc::CrossAccountId, CommonCollectionOperations, CommonWeightInfo, with_weight};
+use pallet_common::{erc::CrossAccountId, CommonCollectionOperations, CommonWeightInfo};
use up_data_structs::TokenId;
pub struct CommonWeights<T: Config>(PhantomData<T>);
@@ -188,17 +184,9 @@
to: <T>::CrossAccountId,
_token: TokenId,
amount: u128,
- _budget: &dyn up_data_structs::budget::Budget,
+ budget: &dyn up_data_structs::budget::Budget,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- with_weight(
- <T as Config>::Currency::transfer(
- sender.as_sub(),
- to.as_sub(),
- amount.into(),
- ExistenceRequirement::KeepAlive,
- ),
- Default::default(),
- )
+ <Pallet<T>>::transfer(self, &sender, &to, amount, budget)
}
fn approve(
@@ -229,20 +217,9 @@
to: <T>::CrossAccountId,
_token: TokenId,
amount: u128,
- _budget: &dyn up_data_structs::budget::Budget,
+ budget: &dyn up_data_structs::budget::Budget,
) -> frame_support::pallet_prelude::DispatchResultWithPostInfo {
- if sender != from {
- fail!(<pallet_common::Error<T>>::NoPermission);
- }
- with_weight(
- <T as Config>::Currency::transfer(
- from.as_sub(),
- to.as_sub(),
- amount.into(),
- ExistenceRequirement::KeepAlive,
- ),
- Default::default(),
- )
+ <Pallet<T>>::transfer_from(self, &sender, &from, &to, amount, budget)
}
fn burn_from(
pallets/balances-adapter/src/erc.rsdiffbeforeafterboth1use crate::{Config, NativeFungibleHandle, SelfWeightOf};1use crate::{Config, NativeFungibleHandle, Pallet, SelfWeightOf};2use evm_coder::{abi::AbiType, ToLog, generate_stubgen, solidity_interface, types::*};2use evm_coder::{abi::AbiType, ToLog, generate_stubgen, solidity_interface, types::*};3use frame_support::traits::{Currency, ExistenceRequirement};3use frame_support::traits::{Currency, ExistenceRequirement};4use pallet_balances::WeightInfo;4use pallet_balances::WeightInfo;10use pallet_evm_coder_substrate::{10use pallet_evm_coder_substrate::{11 call, dispatch_to_evm,11 call, dispatch_to_evm,12 execution::{PreDispatch, Result},12 execution::{PreDispatch, Result},13 frontier_contract,13 frontier_contract, WithRecorder,14};14};15use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};15use sp_core::{U256, Get};16use sp_core::{U256, Get};16use sp_std::vec::Vec;17use sp_std::vec::Vec;171873 let caller = T::CrossAccountId::from_eth(caller);74 let caller = T::CrossAccountId::from_eth(caller);74 let to = T::CrossAccountId::from_eth(to);75 let to = T::CrossAccountId::from_eth(to);75 let amount = amount.try_into().map_err(|_| "amount overflow")?;76 let amount = amount.try_into().map_err(|_| "amount overflow")?;76 // let budget = self77 let budget = self77 // .recorder78 .recorder()78 // .weight_calls_budget(<StructureWeight<T>>::find_parent());79 .weight_calls_budget(<StructureWeight<T>>::find_parent());798080 // <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;81 <T as Config>::Currency::transfer(81 <Pallet<T>>::transfer(self, &caller, &to, amount, &budget)82 caller.as_sub(),83 to.as_sub(),84 amount,85 ExistenceRequirement::KeepAlive,86 )87 .map_err(dispatch_to_evm::<T>)?;82 .map_err(|e| dispatch_to_evm::<T>(e.error))?;88 Ok(true)83 Ok(true)89 }84 }9085100 let from = T::CrossAccountId::from_eth(from);95 let from = T::CrossAccountId::from_eth(from);101 let to = T::CrossAccountId::from_eth(to);96 let to = T::CrossAccountId::from_eth(to);102 let amount = amount.try_into().map_err(|_| "amount overflow")?;97 let amount = amount.try_into().map_err(|_| "amount overflow")?;10398 let budget = self104 if from != caller {105 return Err("no permission".into());99 .recorder()106 }100 .weight_calls_budget(<StructureWeight<T>>::find_parent());107 // let budget = self101108 // .recorder109 // .weight_calls_budget(<StructureWeight<T>>::find_parent());110111 // <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)112 // .map_err(dispatch_to_evm::<T>)?;113 <T as Config>::Currency::transfer(102 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)114 caller.as_sub(),115 to.as_sub(),116 amount,117 ExistenceRequirement::KeepAlive,118 )119 .map_err(dispatch_to_evm::<T>)?;103 .map_err(|e| dispatch_to_evm::<T>(e.error))?;120 Ok(true)104 Ok(true)121 }105 }122}106}pallets/balances-adapter/src/lib.rsdiffbeforeafterboth--- a/pallets/balances-adapter/src/lib.rs
+++ b/pallets/balances-adapter/src/lib.rs
@@ -5,14 +5,17 @@
use core::ops::Deref;
use frame_support::sp_runtime::DispatchResult;
+use pallet_evm_coder_substrate::{WithRecorder, SubstrateRecorder};
pub use pallet::*;
-use pallet_evm_coder_substrate::{WithRecorder, SubstrateRecorder};
pub mod common;
pub mod erc;
pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
+const NATIVE_FUNGIBLE_COLLECTION_ID: up_data_structs::CollectionId =
+ up_data_structs::CollectionId(0);
+
/// Handle for native fungible collection
pub struct NativeFungibleHandle<T: Config>(SubstrateRecorder<T>);
impl<T: Config> NativeFungibleHandle<T> {
@@ -45,14 +48,27 @@
}
#[frame_support::pallet]
pub mod pallet {
+ use super::*;
use alloc::string::String;
- use frame_support::{traits::Get};
+ use frame_support::{
+ dispatch::PostDispatchInfo,
+ ensure,
+ pallet_prelude::{DispatchResultWithPostInfo, Pays},
+ traits::{Currency, ExistenceRequirement, Get},
+ };
use pallet_balances::WeightInfo;
+ use pallet_common::{erc::CrossAccountId, Error as CommonError, Pallet as PalletCommon};
+ use pallet_structure::Pallet as PalletStructure;
use sp_core::U256;
+ use sp_runtime::DispatchError;
+ use up_data_structs::{budget::Budget, mapping::TokenAddressMapping, TokenId};
#[pallet::config]
pub trait Config:
- frame_system::Config + pallet_evm_coder_substrate::Config + pallet_common::Config
+ frame_system::Config
+ + pallet_evm_coder_substrate::Config
+ + pallet_common::Config
+ + pallet_structure::Config
{
/// Currency from `pallet_balances`
type Currency: frame_support::traits::Currency<
@@ -74,4 +90,104 @@
}
#[pallet::pallet]
pub struct Pallet<T>(_);
+
+ impl<T: Config> Pallet<T> {
+ /// Checks if a non-owner has (enough) allowance from the owner to perform operations on the tokens.
+ /// Returns the expected remaining allowance - it should be set manually if the transaction proceeds.
+ ///
+ /// - `collection`: Collection that contains the token.
+ /// - `spender`: CrossAccountId who has the allowance rights.
+ /// - `from`: The owner of the tokens who sets the allowance.
+ /// - `amount`: Amount of tokens by which the allowance sholud be reduced.
+ fn check_allowed(
+ spender: &T::CrossAccountId,
+ from: &T::CrossAccountId,
+ nesting_budget: &dyn Budget,
+ ) -> Result<u128, DispatchError> {
+ if spender.conv_eq(from) {
+ return Ok(0);
+ }
+
+ if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {
+ ensure!(
+ <PalletStructure<T>>::check_indirectly_owned(
+ spender.clone(),
+ source.0,
+ source.1,
+ None,
+ nesting_budget
+ )?,
+ <CommonError<T>>::ApprovedValueTooLow,
+ );
+ } else if spender != from {
+ return Ok(0);
+ }
+
+ Ok(<T as Config>::Currency::free_balance(from.as_sub()).into())
+ }
+
+ /// Transfers the specified amount of tokens. Will check that
+ /// the transfer is allowed for the token.
+ ///
+ /// - `from`: Owner of tokens to transfer.
+ /// - `to`: Recepient of transfered tokens.
+ /// - `amount`: Amount of tokens to transfer.
+ /// - `collection`: Collection that contains the token
+ 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)?;
+
+ if from != to && amount != 0 {
+ <T as Config>::Currency::transfer(
+ from.as_sub(),
+ to.as_sub(),
+ amount.into(),
+ ExistenceRequirement::KeepAlive,
+ )?;
+
+ <PalletStructure<T>>::nest_if_sent_to_token(
+ from.clone(),
+ to,
+ NATIVE_FUNGIBLE_COLLECTION_ID,
+ TokenId::default(),
+ nesting_budget,
+ )?;
+
+ let balance_from: u128 =
+ <T as Config>::Currency::free_balance(from.as_sub()).into();
+ if balance_from == 0 {
+ <PalletStructure<T>>::unnest_if_nested(
+ from,
+ NATIVE_FUNGIBLE_COLLECTION_ID,
+ TokenId::default(),
+ );
+ }
+ };
+
+ Ok(PostDispatchInfo {
+ actual_weight: Some(<SelfWeightOf<T>>::transfer()),
+ pays_fee: Pays::Yes,
+ })
+ }
+
+ pub fn transfer_from(
+ collection: &NativeFungibleHandle<T>,
+ spender: &T::CrossAccountId,
+ from: &T::CrossAccountId,
+ to: &T::CrossAccountId,
+ amount: u128,
+ nesting_budget: &dyn Budget,
+ ) -> DispatchResultWithPostInfo {
+ let allowance = Self::check_allowed(collection, spender, from, amount, nesting_budget)?;
+ if allowance < amount {
+ return Err(<CommonError<T>>::ApprovedValueTooLow.into());
+ }
+ Self::transfer(collection, from, to, amount, nesting_budget)
+ }
+ }
}