Skip to content

Commit

Permalink
Fix/evm fee burning (#1390)
Browse files Browse the repository at this point in the history
* EVM fee burning

* Tests

* Rename

* Redundant entries cleanup

* Miss
  • Loading branch information
Dinonard authored Dec 5, 2024
1 parent d28c0ad commit 29b3bd6
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 80 deletions.
62 changes: 59 additions & 3 deletions primitives/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,18 @@

use crate::{AccountId, AssetId};

use frame_support::ensure;
use pallet_evm::{AddressMapping, HashedAddressMapping};
use frame_support::{
ensure,
traits::{
fungible::{Balanced, Credit},
tokens::{fungible::Inspect, imbalance::OnUnbalanced},
},
};
use pallet_evm::{AddressMapping, HashedAddressMapping, OnChargeEVMTransaction};
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_core::{Hasher, H160, H256};
use sp_core::{Hasher, H160, H256, U256};
use sp_runtime::traits::UniqueSaturatedInto;
use sp_std::marker::PhantomData;

use pallet_assets::AssetsCallback;
Expand Down Expand Up @@ -139,3 +146,52 @@ impl<Address> UnifiedAddress<Address> {
}
}
}

/// Wrapper around the `EvmFungibleAdapter` from the `pallet-evm`.
///
/// While it provides most of the functionality we need,
/// it doesn't allow the tip to be deposited into an arbitrary account.
/// This adapter allows us to do that.
///
/// Two separate `OnUnbalanced` handers are used:
/// - `UOF` for the fee
/// - `OUT` for the tip
pub struct EVMFungibleAdapterWrapper<F, FeeHandler, TipHandler>(
core::marker::PhantomData<(F, FeeHandler, TipHandler)>,
);
impl<T, F, FeeHandler, TipHandler> OnChargeEVMTransaction<T>
for EVMFungibleAdapterWrapper<F, FeeHandler, TipHandler>
where
T: pallet_evm::Config,
F: Balanced<T::AccountId>,
FeeHandler: OnUnbalanced<Credit<T::AccountId, F>>,
TipHandler: OnUnbalanced<Credit<T::AccountId, F>>,
U256: UniqueSaturatedInto<<F as Inspect<<T as frame_system::Config>::AccountId>>::Balance>,
{
// Kept type as Option to satisfy bound of Default
type LiquidityInfo = Option<Credit<T::AccountId, F>>;

fn withdraw_fee(who: &H160, fee: U256) -> Result<Self::LiquidityInfo, pallet_evm::Error<T>> {
pallet_evm::EVMFungibleAdapter::<F, FeeHandler>::withdraw_fee(who, fee)
}

fn correct_and_deposit_fee(
who: &H160,
corrected_fee: U256,
base_fee: U256,
already_withdrawn: Self::LiquidityInfo,
) -> Self::LiquidityInfo {
<pallet_evm::EVMFungibleAdapter::<F, FeeHandler> as OnChargeEVMTransaction<T>>::correct_and_deposit_fee(
who,
corrected_fee,
base_fee,
already_withdrawn,
)
}

fn pay_priority_fee(tip: Self::LiquidityInfo) {
if let Some(tip) = tip {
TipHandler::on_unbalanceds(Some(tip).into_iter());
}
}
}
37 changes: 15 additions & 22 deletions runtime/astar/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ use astar_primitives::{
AccountCheck as DappStakingAccountCheck, CycleConfiguration, DAppId, EraNumber,
PeriodNumber, RankedTier, SmartContract, StandardTierSlots,
},
evm::EvmRevertCodeHandler,
evm::{EVMFungibleAdapterWrapper, EvmRevertCodeHandler},
governance::{
CommunityCouncilCollectiveInst, CommunityCouncilMembershipInst, CommunityTreasuryInst,
EnsureRootOrAllMainCouncil, EnsureRootOrAllTechnicalCommittee,
Expand Down Expand Up @@ -474,7 +474,7 @@ impl pallet_inflation::PayoutPerBlock<Credit<AccountId, Balances>> for Inflation
}

fn collators(reward: Credit<AccountId, Balances>) {
ToStakingPot::on_unbalanced(reward);
CollatorRewardPot::on_unbalanced(reward);
}
}

Expand Down Expand Up @@ -614,8 +614,8 @@ parameter_types! {
pub TreasuryAccountId: AccountId = TreasuryPalletId::get().into_account_truncating();
}

pub struct ToStakingPot;
impl OnUnbalanced<Credit<AccountId, Balances>> for ToStakingPot {
pub struct CollatorRewardPot;
impl OnUnbalanced<Credit<AccountId, Balances>> for CollatorRewardPot {
fn on_nonzero_unbalanced(amount: Credit<AccountId, Balances>) {
let staking_pot = PotId::get().into_account_truncating();
let _ = Balances::resolve(&staking_pot, amount);
Expand Down Expand Up @@ -838,9 +838,13 @@ impl OnUnbalanced<Credit<AccountId, Balances>> for DealWithFees {
drop(to_burn);

// pay fees to collator
<ToStakingPot as OnUnbalanced<_>>::on_unbalanced(collator);
<CollatorRewardPot as OnUnbalanced<_>>::on_unbalanced(collator);
}
}

fn on_unbalanced(amount: Credit<AccountId, Balances>) {
Self::on_unbalanceds(Some(amount).into_iter());
}
}

impl pallet_transaction_payment::Config for Runtime {
Expand Down Expand Up @@ -946,7 +950,7 @@ impl pallet_evm::Config for Runtime {
type PrecompilesType = Precompiles;
type PrecompilesValue = PrecompilesValue;
type ChainId = ChainId;
type OnChargeTransaction = pallet_evm::EVMFungibleAdapter<Balances, ToStakingPot>;
type OnChargeTransaction = EVMFungibleAdapterWrapper<Balances, DealWithFees, CollatorRewardPot>;
type BlockGasLimit = BlockGasLimit;
type Timestamp = Timestamp;
type OnCreate = ();
Expand Down Expand Up @@ -1026,7 +1030,7 @@ pub enum ProxyType {
/// Allows all runtime calls for proxy account
Any,
/// Allows only NonTransfer runtime calls for proxy account
/// To know exact calls check InstanceFilter inmplementation for ProxyTypes
/// To know exact calls check InstanceFilter implementation for ProxyTypes
NonTransfer,
/// All Runtime calls from Pallet Balances allowed for proxy account
Balances,
Expand Down Expand Up @@ -1062,26 +1066,15 @@ impl InstanceFilter<RuntimeCall> for ProxyType {
c,
RuntimeCall::System(..)
| RuntimeCall::Identity(..)
| RuntimeCall::Timestamp(..)
| RuntimeCall::Multisig(..)
| RuntimeCall::Proxy(..)
| RuntimeCall::ParachainSystem(..)
| RuntimeCall::ParachainInfo(..)
// Skip entire Balances pallet
| RuntimeCall::Vesting(pallet_vesting::Call::vest{..})
| RuntimeCall::Vesting(pallet_vesting::Call::vest_other{..})
// Specifically omitting Vesting `vested_transfer`, and `force_vested_transfer`
| RuntimeCall::Vesting(
pallet_vesting::Call::vest { .. }
| pallet_vesting::Call::vest_other { .. }
)
| RuntimeCall::DappStaking(..)
// Skip entire Assets pallet
| RuntimeCall::CollatorSelection(..)
| RuntimeCall::Session(..)
| RuntimeCall::XcmpQueue(..)
| RuntimeCall::PolkadotXcm(..)
| RuntimeCall::CumulusXcm(..)
| RuntimeCall::XcAssetConfig(..)
// Skip entire EVM pallet
// Skip entire Ethereum pallet
| RuntimeCall::DynamicEvmBaseFee(..) // Skip entire Contracts pallet
)
}
ProxyType::Balances => {
Expand Down
14 changes: 4 additions & 10 deletions runtime/local/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -811,18 +811,12 @@ impl InstanceFilter<RuntimeCall> for ProxyType {
matches!(
c,
RuntimeCall::System(..)
| RuntimeCall::Timestamp(..)
| RuntimeCall::Scheduler(..)
| RuntimeCall::Proxy(..)
| RuntimeCall::Grandpa(..)
// Skip entire Balances pallet
| RuntimeCall::Vesting(pallet_vesting::Call::vest{..})
| RuntimeCall::Vesting(pallet_vesting::Call::vest_other{..})
// Specifically omitting Vesting `vested_transfer`, and `force_vested_transfer`
| RuntimeCall::Vesting(
pallet_vesting::Call::vest { .. }
| pallet_vesting::Call::vest_other { .. }
)
| RuntimeCall::DappStaking(..)
// Skip entire EVM pallet
// Skip entire Ethereum pallet
| RuntimeCall::DynamicEvmBaseFee(..) // Skip entire Contracts pallet
)
}
// All Runtime calls from Pallet Balances allowed for proxy account
Expand Down
37 changes: 14 additions & 23 deletions runtime/shibuya/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ use astar_primitives::{
AccountCheck as DappStakingAccountCheck, CycleConfiguration, DAppId, EraNumber,
PeriodNumber, RankedTier, SmartContract, StandardTierSlots,
},
evm::{EvmRevertCodeHandler, HashedDefaultMappings},
evm::{EVMFungibleAdapterWrapper, EvmRevertCodeHandler, HashedDefaultMappings},
governance::{
CommunityCouncilCollectiveInst, CommunityCouncilMembershipInst, CommunityTreasuryInst,
EnsureRootOrAllMainCouncil, EnsureRootOrAllTechnicalCommittee,
Expand Down Expand Up @@ -497,7 +497,7 @@ impl pallet_inflation::PayoutPerBlock<Credit<AccountId, Balances>> for Inflation
}

fn collators(reward: Credit<AccountId, Balances>) {
ToStakingPot::on_unbalanced(reward);
CollatorRewardPot::on_unbalanced(reward);
}
}

Expand Down Expand Up @@ -638,8 +638,8 @@ parameter_types! {
pub TreasuryAccountId: AccountId = TreasuryPalletId::get().into_account_truncating();
}

pub struct ToStakingPot;
impl OnUnbalanced<Credit<AccountId, Balances>> for ToStakingPot {
pub struct CollatorRewardPot;
impl OnUnbalanced<Credit<AccountId, Balances>> for CollatorRewardPot {
fn on_nonzero_unbalanced(amount: Credit<AccountId, Balances>) {
let staking_pot = PotId::get().into_account_truncating();
let _ = Balances::resolve(&staking_pot, amount);
Expand Down Expand Up @@ -834,9 +834,13 @@ impl OnUnbalanced<Credit<AccountId, Balances>> for DealWithFees {
drop(to_burn);

// pay fees to collator
<ToStakingPot as OnUnbalanced<_>>::on_unbalanced(collator);
<CollatorRewardPot as OnUnbalanced<_>>::on_unbalanced(collator);
}
}

fn on_unbalanced(amount: Credit<AccountId, Balances>) {
Self::on_unbalanceds(Some(amount).into_iter());
}
}

impl pallet_transaction_payment::Config for Runtime {
Expand Down Expand Up @@ -947,7 +951,7 @@ impl pallet_evm::Config for Runtime {
// Ethereum-compatible chain_id:
// * Shibuya: 81
type ChainId = EVMChainId;
type OnChargeTransaction = pallet_evm::EVMFungibleAdapter<Balances, ToStakingPot>;
type OnChargeTransaction = EVMFungibleAdapterWrapper<Balances, DealWithFees, CollatorRewardPot>;
type BlockGasLimit = BlockGasLimit;
type Timestamp = Timestamp;
type OnCreate = ();
Expand Down Expand Up @@ -1042,27 +1046,14 @@ impl InstanceFilter<RuntimeCall> for ProxyType {
c,
RuntimeCall::System(..)
| RuntimeCall::Identity(..)
| RuntimeCall::Timestamp(..)
| RuntimeCall::Multisig(..)
| RuntimeCall::Scheduler(..)
| RuntimeCall::Proxy(..)
| RuntimeCall::ParachainSystem(..)
| RuntimeCall::ParachainInfo(..)
// Skip entire Balances pallet
| RuntimeCall::Vesting(pallet_vesting::Call::vest{..})
| RuntimeCall::Vesting(pallet_vesting::Call::vest_other{..})
// Specifically omitting Vesting `vested_transfer`, and `force_vested_transfer`
| RuntimeCall::Vesting(
pallet_vesting::Call::vest { .. }
| pallet_vesting::Call::vest_other { .. }
)
| RuntimeCall::DappStaking(..)
// Skip entire Assets pallet
| RuntimeCall::CollatorSelection(..)
| RuntimeCall::Session(..)
| RuntimeCall::XcmpQueue(..)
| RuntimeCall::PolkadotXcm(..)
| RuntimeCall::CumulusXcm(..)
| RuntimeCall::XcAssetConfig(..)
// Skip entire EVM pallet
// Skip entire Ethereum pallet
| RuntimeCall::DynamicEvmBaseFee(..) // Skip entire Contracts pallet
)
}
// All Runtime calls from Pallet Balances allowed for proxy account
Expand Down
36 changes: 14 additions & 22 deletions runtime/shiden/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ use astar_primitives::{
AccountCheck as DappStakingAccountCheck, CycleConfiguration, DAppId, EraNumber,
PeriodNumber, RankedTier, SmartContract, TierSlots as TierSlotsFunc,
},
evm::EvmRevertCodeHandler,
evm::{EVMFungibleAdapterWrapper, EvmRevertCodeHandler},
governance::OracleMembershipInst,
oracle::{CurrencyAmount, CurrencyId, DummyCombineData, Price},
xcm::AssetLocationIdConverter,
Expand Down Expand Up @@ -462,7 +462,7 @@ impl pallet_inflation::PayoutPerBlock<Credit<AccountId, Balances>> for Inflation
}

fn collators(reward: Credit<AccountId, Balances>) {
ToStakingPot::on_unbalanced(reward);
CollatorRewardPot::on_unbalanced(reward);
}
}

Expand Down Expand Up @@ -601,8 +601,8 @@ parameter_types! {
pub TreasuryAccountId: AccountId = TreasuryPalletId::get().into_account_truncating();
}

pub struct ToStakingPot;
impl OnUnbalanced<Credit<AccountId, Balances>> for ToStakingPot {
pub struct CollatorRewardPot;
impl OnUnbalanced<Credit<AccountId, Balances>> for CollatorRewardPot {
fn on_nonzero_unbalanced(amount: Credit<AccountId, Balances>) {
let staking_pot = PotId::get().into_account_truncating();
let _ = Balances::resolve(&staking_pot, amount);
Expand Down Expand Up @@ -813,9 +813,13 @@ impl OnUnbalanced<Credit<AccountId, Balances>> for DealWithFees {
drop(to_burn);

// pay fees to collator
<ToStakingPot as OnUnbalanced<_>>::on_unbalanced(collator);
<CollatorRewardPot as OnUnbalanced<_>>::on_unbalanced(collator);
}
}

fn on_unbalanced(amount: Credit<AccountId, Balances>) {
Self::on_unbalanceds(Some(amount).into_iter());
}
}

impl pallet_transaction_payment::Config for Runtime {
Expand Down Expand Up @@ -920,7 +924,7 @@ impl pallet_evm::Config for Runtime {
type PrecompilesType = Precompiles;
type PrecompilesValue = PrecompilesValue;
type ChainId = ChainId;
type OnChargeTransaction = pallet_evm::EVMFungibleAdapter<Balances, ToStakingPot>;
type OnChargeTransaction = EVMFungibleAdapterWrapper<Balances, DealWithFees, CollatorRewardPot>;
type BlockGasLimit = BlockGasLimit;
type Timestamp = Timestamp;
type OnCreate = ();
Expand Down Expand Up @@ -1007,26 +1011,14 @@ impl InstanceFilter<RuntimeCall> for ProxyType {
c,
RuntimeCall::System(..)
| RuntimeCall::Identity(..)
| RuntimeCall::Timestamp(..)
| RuntimeCall::Multisig(..)
| RuntimeCall::Proxy(..)
| RuntimeCall::ParachainSystem(..)
| RuntimeCall::ParachainInfo(..)
// Skip entire Balances pallet
| RuntimeCall::Vesting(pallet_vesting::Call::vest{..})
| RuntimeCall::Vesting(pallet_vesting::Call::vest_other{..})
// Specifically omitting Vesting `vested_transfer`, and `force_vested_transfer`
| RuntimeCall::Vesting(
pallet_vesting::Call::vest { .. }
| pallet_vesting::Call::vest_other { .. }
)
| RuntimeCall::DappStaking(..)
// Skip entire Assets pallet
| RuntimeCall::CollatorSelection(..)
| RuntimeCall::Session(..)
| RuntimeCall::XcmpQueue(..)
| RuntimeCall::PolkadotXcm(..)
| RuntimeCall::CumulusXcm(..)
| RuntimeCall::XcAssetConfig(..)
// Skip entire EVM pallet
// Skip entire Ethereum pallet
| RuntimeCall::DynamicEvmBaseFee(..) // Skip entire Contracts pallet
)
}
ProxyType::Balances => {
Expand Down
Loading

0 comments on commit 29b3bd6

Please sign in to comment.