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

difftreelog

refactor extract evm transaction payment

Yaroslav Bolyukin2021-07-27parent: #60ea0ef.patch.diff
in: master

3 files changed

addedpallets/evm-transaction-payment/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-transaction-payment/Cargo.toml
@@ -0,0 +1,37 @@
+[package]
+name = "pallet-evm-transaction-payment"
+version = "0.1.0"
+edition = "2018"
+
+[dependencies]
+frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-io = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-core = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+pallet-evm = { default-features = false, version = "5.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fp-evm = { default-features = false, version = "2.0.0", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+pallet-ethereum = { default-features = false, version = "3.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+up-sponsorship = { default-features = false, path = '../../primitives/sponsorship' }
+
+[dependencies.codec]
+default-features = false
+features = ['derive']
+package = 'parity-scale-codec'
+version = '2.0.0'
+
+[features]
+default = ["std"]
+std = [
+    "frame-support/std",
+    "frame-system/std",
+    "sp-runtime/std",
+    "sp-std/std",
+    "sp-io/std",
+    "sp-core/std",
+    "pallet-evm/std",
+    "pallet-ethereum/std",
+    "fp-evm/std",
+    "up-sponsorship/std",
+]
addedpallets/evm-transaction-payment/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-transaction-payment/src/lib.rs
@@ -0,0 +1,98 @@
+#![cfg_attr(not(feature = "std"), no_std)]
+
+pub use pallet::*;
+
+#[frame_support::pallet]
+pub mod pallet {
+	use core::marker::PhantomData;
+	use frame_support::traits::Currency;
+	use pallet_evm::EVMCurrencyAdapter;
+	use fp_evm::WithdrawReason;
+	use sp_core::{H160, U256};
+	use sp_runtime::TransactionOutcome;
+	use up_sponsorship::SponsorshipHandler;
+	use sp_std::vec::Vec;
+
+	type NegativeImbalanceOf<C, T> =
+		<C as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance;
+
+	#[pallet::config]
+	pub trait Config: frame_system::Config {
+		type SponsorshipHandler: SponsorshipHandler<H160, (H160, Vec<u8>)>;
+		type Currency: Currency<Self::AccountId>;
+	}
+
+	#[pallet::pallet]
+	#[pallet::generate_store(pub(super) trait Store)]
+	pub struct Pallet<T>(_);
+
+	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>);
+	impl<T: Config> fp_evm::TransactionValidityHack for TransactionValidityHack<T> {
+		fn who_pays_fee(origin: H160, reason: &WithdrawReason) -> Option<H160> {
+			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(|| {
+						TransactionOutcome::Rollback(T::SponsorshipHandler::get_sponsor(
+							&origin,
+							&(*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: &H160,
+			reason: WithdrawReason,
+			fee: U256,
+		) -> core::result::Result<Self::LiquidityInfo, pallet_evm::Error<T>> {
+			let mut who_pays_fee = *who;
+			if let WithdrawReason::Call { target, input } = &reason {
+				who_pays_fee = T::SponsorshipHandler::get_sponsor(who, &(*target, input.clone()))
+					.unwrap_or(who_pays_fee);
+			}
+			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,
+				negative_imbalance: i,
+			}))
+		}
+
+		fn correct_and_deposit_fee(
+			who: &H160,
+			corrected_fee: U256,
+			already_withdrawn: Self::LiquidityInfo,
+		) -> core::result::Result<(), pallet_evm::Error<T>> {
+			EVMCurrencyAdapter::<<T as Config>::Currency, ()>::correct_and_deposit_fee(
+				&already_withdrawn.as_ref().map(|e| e.who).unwrap_or(*who),
+				corrected_fee,
+				already_withdrawn.map(|e| e.negative_imbalance),
+			)
+		}
+	}
+}
modifiedpallets/nft/src/eth/sponsoring.rsdiffbeforeafterboth
1//! Implements EVM sponsoring logic via OnChargeEVMTransaction1//! Implements EVM sponsoring logic via OnChargeEVMTransaction
22
3use crate::{3use crate::{
4 Collection, ChainLimit, CollectionById, Config, NftTransferBasket, FungibleTransferBasket,4 ChainLimit, Collection, CollectionById, Config, FungibleTransferBasket, NftTransferBasket,
5 eth::account::EvmBackwardsAddressMapping,5 eth::{account::EvmBackwardsAddressMapping, map_eth_to_id},
6};6};
7use evm_coder::abi::AbiReader;7use evm_coder::{Call, abi::AbiReader};
8use frame_support::{8use frame_support::{
9 storage::{StorageMap, StorageDoubleMap, StorageValue},9 storage::{StorageMap, StorageDoubleMap, StorageValue},
10 traits::Currency,
11};10};
12use pallet_evm::{EVMCurrencyAdapter, WithdrawReason};
13use sp_core::{H160, U256};11use sp_core::H160;
14use sp_std::prelude::*;12use sp_std::prelude::*;
13use up_sponsorship::SponsorshipHandler;
15use super::{14use super::{
16 account::CrossAccountId,15 account::CrossAccountId,
17 erc::{UniqueFungibleCall, UniqueNFTCall, ERC721Call, ERC20Call, ERC721UniqueExtensionsCall},16 erc::{UniqueFungibleCall, UniqueNFTCall, ERC721Call, ERC20Call, ERC721UniqueExtensionsCall},
18};17};
19use core::convert::TryInto;18use core::convert::TryInto;
20
21type NegativeImbalanceOf<C, T> =
22 <C as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance;19use core::marker::PhantomData;
23
24pub struct ChargeEvmTransaction;
25pub struct ChargeEvmLiquidityInfo<T>
26where
27 T: Config,
28 T: pallet_evm::Config,
29{
30 who: H160,
31 negative_imbalance: NegativeImbalanceOf<<T as Config>::Currency, T>,
32}
3320
34struct AnyError;21struct AnyError;
3522
46 .map_err(|_| AnyError)?33 .map_err(|_| AnyError)?
47 .ok_or(AnyError)?;34 .ok_or(AnyError)?;
48 match call {35 match call {
49 UniqueNFTCall::ERC721UniqueExtensions(ERC721UniqueExtensionsCall::Transfer {36 UniqueNFTCall::ERC721UniqueExtensions(
50 token_id,37 ERC721UniqueExtensionsCall::TransferNft { token_id, .. },
51 ..
52 })38 )
53 | UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, .. }) => {39 | UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, .. }) => {
118 Err(AnyError)104 Err(AnyError)
119}105}
120106
107pub struct NftEthSponsorshipHandler<T: Config>(PhantomData<*const T>);
121impl<T> pallet_evm::OnChargeEVMTransaction<T> for ChargeEvmTransaction108impl<T: Config> SponsorshipHandler<H160, (H160, Vec<u8>)> for NftEthSponsorshipHandler<T> {
122where
123 T: Config,
124 T: pallet_evm::Config,
125{
126 type LiquidityInfo = Option<ChargeEvmLiquidityInfo<T>>;
127
128 fn withdraw_fee(109 fn get_sponsor(who: &H160, call: &(H160, Vec<u8>)) -> Option<H160> {
129 who: &H160,
130 reason: WithdrawReason,
131 fee: U256,
132 ) -> Result<Self::LiquidityInfo, pallet_evm::Error<T>> {
133 let mut who_pays_fee = *who;
134 if let WithdrawReason::Call { target, input } = &reason {110 if let Some(collection_id) = map_eth_to_id(&call.0) {
135 if let Some(collection_id) = crate::eth::map_eth_to_id(target) {
136 if let Some(collection) = <CollectionById<T>>::get(collection_id) {111 if let Some(collection) = <CollectionById<T>>::get(collection_id) {
137 if let Some(sponsor) = collection.sponsorship.sponsor() {112 if !collection.sponsorship.confirmed() {
113 return None;
114 }
138 if try_sponsor(who, collection_id, &collection, input).is_ok() {115 if try_sponsor(who, collection_id, &collection, &call.1).is_ok() {
139 who_pays_fee =116 return collection
117 .sponsorship
118 .sponsor()
119 .cloned()
140 T::EvmBackwardsAddressMapping::from_account_id(sponsor.clone());120 .map(T::EvmBackwardsAddressMapping::from_account_id);
141 }121 }
142 }
143 }122 }
144 }123 }
145 }124 None
146
147 // TODO: Pay fee from substrate address
148 let negative_imbalance = EVMCurrencyAdapter::<<T as Config>::Currency, ()>::withdraw_fee(
149 &who_pays_fee,
150 reason,
151 fee,
152 )?;
153 Ok(negative_imbalance.map(|i| ChargeEvmLiquidityInfo {
154 who: who_pays_fee,
155 negative_imbalance: i,
156 }))
157 }125 }
158126}
159 fn correct_and_deposit_fee(
160 who: &H160,
161 corrected_fee: U256,
162 already_withdrawn: Self::LiquidityInfo,
163 ) -> Result<(), pallet_evm::Error<T>> {
164 EVMCurrencyAdapter::<<T as Config>::Currency, ()>::correct_and_deposit_fee(
165 &already_withdrawn.as_ref().map(|e| e.who).unwrap_or(*who),
166 corrected_fee,
167 already_withdrawn.map(|e| e.negative_imbalance),
168 )
169 }
170}
171127