git.delta.rocks / unique-network / refs/commits / d191478d543b

difftreelog

refactor move evm sponsoring effects to validity

Yaroslav Bolyukin2022-05-04parent: #1f6cb5b.patch.diff
in: master

5 files changed

modifiedpallets/evm-transaction-payment/src/lib.rsdiffbeforeafterboth
--- a/pallets/evm-transaction-payment/src/lib.rs
+++ b/pallets/evm-transaction-payment/src/lib.rs
@@ -20,8 +20,8 @@
 use fp_evm::WithdrawReason;
 use frame_support::traits::{Currency, IsSubType};
 pub use pallet::*;
-use pallet_evm::{EVMCurrencyAdapter, EnsureAddressOrigin, account::CrossAccountId};
-use sp_core::{H160, U256};
+use pallet_evm::{EnsureAddressOrigin, account::CrossAccountId};
+use sp_core::H160;
 use sp_runtime::{TransactionOutcome, DispatchError};
 use up_sponsorship::SponsorshipHandler;
 
@@ -41,18 +41,6 @@
 	#[pallet::pallet]
 	#[pallet::generate_store(pub(super) trait Store)]
 	pub struct Pallet<T>(_);
-}
-
-type NegativeImbalanceOf<C, T> =
-	<C as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance;
-
-pub struct ChargeEvmLiquidityInfo<T>
-where
-	T: Config,
-	T: pallet_evm::Config,
-{
-	who: H160,
-	negative_imbalance: NegativeImbalanceOf<<T as Config>::Currency, T>,
 }
 
 pub struct TransactionValidityHack<T: Config>(PhantomData<*const T>);
@@ -60,69 +48,11 @@
 	fn who_pays_fee(origin: H160, reason: &WithdrawReason) -> Option<T::CrossAccountId> {
 		match reason {
 			WithdrawReason::Call { target, input } => {
-				// This method is only used for checking, we shouldn't touch storage in it
-				frame_support::storage::with_transaction(|| {
-					let origin_sub = T::CrossAccountId::from_eth(origin);
-					TransactionOutcome::Rollback(Ok::<_, DispatchError>(
-						T::EvmSponsorshipHandler::get_sponsor(
-							&origin_sub,
-							&(*target, input.clone()),
-						),
-					))
-				})
-				// FIXME: it may fail with DispatchError in case of depth limit
-				.ok()?
+				let origin_sub = T::CrossAccountId::from_eth(origin);
+				T::EvmSponsorshipHandler::get_sponsor(&origin_sub, &(*target, input.clone()))
 			}
 			_ => None,
 		}
-	}
-}
-pub struct OnChargeTransaction<T: Config>(PhantomData<*const T>);
-impl<T> pallet_evm::OnChargeEVMTransaction<T> for OnChargeTransaction<T>
-where
-	T: Config,
-	T: pallet_evm::Config,
-{
-	type LiquidityInfo = Option<ChargeEvmLiquidityInfo<T>>;
-
-	fn withdraw_fee(
-		who: &T::CrossAccountId,
-		reason: WithdrawReason,
-		fee: U256,
-	) -> core::result::Result<Self::LiquidityInfo, pallet_evm::Error<T>> {
-		let who_pays_fee = if let WithdrawReason::Call { target, input } = &reason {
-			T::EvmSponsorshipHandler::get_sponsor(who, &(*target, input.clone()))
-				.unwrap_or(who.clone())
-		} else {
-			who.clone()
-		};
-
-		let negative_imbalance = EVMCurrencyAdapter::<<T as Config>::Currency, ()>::withdraw_fee(
-			&who_pays_fee,
-			reason,
-			fee,
-		)?;
-
-		Ok(negative_imbalance.map(|i| ChargeEvmLiquidityInfo {
-			who: who_pays_fee.as_eth().clone(),
-			negative_imbalance: i,
-		}))
-	}
-
-	fn correct_and_deposit_fee(
-		who: &T::CrossAccountId,
-		corrected_fee: U256,
-		already_withdrawn: Self::LiquidityInfo,
-	) {
-		<EVMCurrencyAdapter<<T as Config>::Currency, ()> as pallet_evm::OnChargeEVMTransaction<T>>::correct_and_deposit_fee(
-			&already_withdrawn.as_ref().map(|e| T::CrossAccountId::from_eth(e.who)).unwrap_or(who.clone()),
-			corrected_fee,
-			already_withdrawn.map(|e| e.negative_imbalance),
-		)
-	}
-
-	fn pay_priority_fee(tip: U256) {
-		<EVMCurrencyAdapter<<T as Config>::Currency, ()> as pallet_evm::OnChargeEVMTransaction<T>>::pay_priority_fee(tip)
 	}
 }
 
@@ -147,7 +77,7 @@
 				)
 				.ok()?;
 				let who = T::CrossAccountId::from_sub(who.clone());
-				// Effects from EvmSponsorshipHandler are applied in OnChargeEvmTransaction by pallet_evm::runner
+				// Effects from EvmSponsorshipHandler are applied by pallet_evm::runner
 				// TODO: Should we implement simulation mode (test, but do not apply effects) in `up-sponsorship`?
 				let sponsor = frame_support::storage::with_transaction(|| {
 					TransactionOutcome::Rollback(Ok::<_, DispatchError>(
modifiedpallets/unique/src/eth/sponsoring.rsdiffbeforeafterboth
before · pallets/unique/src/eth/sponsoring.rs
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//! Implements EVM sponsoring logic via OnChargeEVMTransaction1819use crate::{Config, sponsorship::*};20use evm_coder::{Call, abi::AbiReader};21use pallet_common::{CollectionHandle, eth::map_eth_to_id};22use sp_core::H160;23use sp_std::prelude::*;24use up_sponsorship::SponsorshipHandler;25use core::marker::PhantomData;26use core::convert::TryInto;27use pallet_evm::account::CrossAccountId;2829use pallet_nonfungible::erc::{30	UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call,31};32use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};33use up_data_structs::{TokenId, CreateItemData, CreateNftData};3435pub struct UniqueEthSponsorshipHandler<T: Config>(PhantomData<*const T>);36impl<T: Config> SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)>37	for UniqueEthSponsorshipHandler<T>38{39	fn get_sponsor(who: &T::CrossAccountId, call: &(H160, Vec<u8>)) -> Option<T::CrossAccountId> {40		let collection_id = map_eth_to_id(&call.0)?;41		let collection = <CollectionHandle<T>>::new(collection_id)?;42		let sponsor = collection.sponsorship.sponsor()?.clone();43		let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;44		Some(T::CrossAccountId::from_sub(match &collection.mode {45			crate::CollectionMode::NFT => {46				let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;47				match call {48					UniqueNFTCall::ERC721UniqueExtensions(49						ERC721UniqueExtensionsCall::Transfer { token_id, .. },50					) => {51						let token_id: TokenId = token_id.try_into().ok()?;52						withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)53					}54					UniqueNFTCall::ERC721Mintable(55						ERC721MintableCall::Mint { token_id, .. }56						| ERC721MintableCall::MintWithTokenUri { token_id, .. },57					) => {58						let _token_id: TokenId = token_id.try_into().ok()?;59						withdraw_create_item::<T>(60							&collection,61							&who,62							&CreateItemData::NFT(CreateNftData::default()),63						)64						.map(|()| sponsor)65					}66					UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, from, .. }) => {67						let token_id: TokenId = token_id.try_into().ok()?;68						let from = T::CrossAccountId::from_eth(from);69						withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)70					}71					UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {72						let token_id: TokenId = token_id.try_into().ok()?;73						withdraw_approve::<T>(&collection, who.as_sub(), &token_id)74							.map(|()| sponsor)75					}76					_ => None,77				}78			}79			crate::CollectionMode::Fungible(_) => {80				let call = <UniqueFungibleCall<T>>::parse(method_id, &mut reader).ok()??;81				#[allow(clippy::single_match)]82				match call {83					UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {84						withdraw_transfer::<T>(&collection, who, &TokenId::default())85							.map(|()| sponsor)86					}87					UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {88						let from = T::CrossAccountId::from_eth(from);89						withdraw_transfer::<T>(&collection, &from, &TokenId::default())90							.map(|()| sponsor)91					}92					UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {93						withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())94							.map(|()| sponsor)95					}96					_ => None,97				}98			}99			_ => None,100		}?))101	}102}
after · pallets/unique/src/eth/sponsoring.rs
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//! Implements EVM sponsoring logic via TransactionValidityHack1819use crate::{Config, sponsorship::*};20use evm_coder::{Call, abi::AbiReader};21use pallet_common::{CollectionHandle, eth::map_eth_to_id};22use sp_core::H160;23use sp_std::prelude::*;24use up_sponsorship::SponsorshipHandler;25use core::marker::PhantomData;26use core::convert::TryInto;27use pallet_evm::account::CrossAccountId;2829use pallet_nonfungible::erc::{30	UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call,31};32use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};33use up_data_structs::{TokenId, CreateItemData, CreateNftData};3435pub struct UniqueEthSponsorshipHandler<T: Config>(PhantomData<*const T>);36impl<T: Config> SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)>37	for UniqueEthSponsorshipHandler<T>38{39	fn get_sponsor(who: &T::CrossAccountId, call: &(H160, Vec<u8>)) -> Option<T::CrossAccountId> {40		let collection_id = map_eth_to_id(&call.0)?;41		let collection = <CollectionHandle<T>>::new(collection_id)?;42		let sponsor = collection.sponsorship.sponsor()?.clone();43		let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;44		Some(T::CrossAccountId::from_sub(match &collection.mode {45			crate::CollectionMode::NFT => {46				let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;47				match call {48					UniqueNFTCall::ERC721UniqueExtensions(49						ERC721UniqueExtensionsCall::Transfer { token_id, .. },50					) => {51						let token_id: TokenId = token_id.try_into().ok()?;52						withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)53					}54					UniqueNFTCall::ERC721Mintable(55						ERC721MintableCall::Mint { token_id, .. }56						| ERC721MintableCall::MintWithTokenUri { token_id, .. },57					) => {58						let _token_id: TokenId = token_id.try_into().ok()?;59						withdraw_create_item::<T>(60							&collection,61							&who,62							&CreateItemData::NFT(CreateNftData::default()),63						)64						.map(|()| sponsor)65					}66					UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, from, .. }) => {67						let token_id: TokenId = token_id.try_into().ok()?;68						let from = T::CrossAccountId::from_eth(from);69						withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)70					}71					UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {72						let token_id: TokenId = token_id.try_into().ok()?;73						withdraw_approve::<T>(&collection, who.as_sub(), &token_id)74							.map(|()| sponsor)75					}76					_ => None,77				}78			}79			crate::CollectionMode::Fungible(_) => {80				let call = <UniqueFungibleCall<T>>::parse(method_id, &mut reader).ok()??;81				#[allow(clippy::single_match)]82				match call {83					UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {84						withdraw_transfer::<T>(&collection, who, &TokenId::default())85							.map(|()| sponsor)86					}87					UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {88						let from = T::CrossAccountId::from_eth(from);89						withdraw_transfer::<T>(&collection, &from, &TokenId::default())90							.map(|()| sponsor)91					}92					UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {93						withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())94							.map(|()| sponsor)95					}96					_ => None,97				}98			}99			_ => None,100		}?))101	}102}
modifiedruntime/opal/src/lib.rsdiffbeforeafterboth
--- a/runtime/opal/src/lib.rs
+++ b/runtime/opal/src/lib.rs
@@ -301,7 +301,7 @@
 	type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
 	type ChainId = ChainId;
 	type Runner = pallet_evm::runner::stack::Runner<Self>;
-	type OnChargeTransaction = pallet_evm_transaction_payment::OnChargeTransaction<Self>;
+	type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;
 	type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;
 	type FindAuthor = EthereumFindAuthor<Aura>;
 }
modifiedruntime/quartz/src/lib.rsdiffbeforeafterboth
--- a/runtime/quartz/src/lib.rs
+++ b/runtime/quartz/src/lib.rs
@@ -280,7 +280,7 @@
 	type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
 	type ChainId = ChainId;
 	type Runner = pallet_evm::runner::stack::Runner<Self>;
-	type OnChargeTransaction = pallet_evm_transaction_payment::OnChargeTransaction<Self>;
+	type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;
 	type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;
 	type FindAuthor = EthereumFindAuthor<Aura>;
 }
modifiedruntime/unique/src/lib.rsdiffbeforeafterboth
--- a/runtime/unique/src/lib.rs
+++ b/runtime/unique/src/lib.rs
@@ -279,7 +279,7 @@
 	type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
 	type ChainId = ChainId;
 	type Runner = pallet_evm::runner::stack::Runner<Self>;
-	type OnChargeTransaction = pallet_evm_transaction_payment::OnChargeTransaction<Self>;
+	type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;
 	type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;
 	type FindAuthor = EthereumFindAuthor<Aura>;
 }