0

I've implemented a POA EVM-Compatible chain using the Frontier node template on branch polkadot-v0.9.22.

I've Implemented a DealWithFees struct and let some part of fees be added to a treasury i've implemented. I'm running all the defaults which came with Frontier's node template having made no changes to pallet evm, ethereum, baseFee or dynamic_fee's configs.

Ive set pallet EVM's OnChargeTransaction to EVMCurrencyAdapter<Balances, DealWithFees>.

But after executing an EVM transaction, no change is observed in the treasury.

NOTE I have fixed the fee for every transaction at 250,000,000,000 balance.


pub struct ToAuthor<R>(sp_std::marker::PhantomData<R>);
impl<R> OnUnbalanced<NegativeImbalance<R>> for ToAuthor<R>
where
    R: pallet_balances::Config + pallet_authorship::Config,
    <R as frame_system::Config>::AccountId: From<AccountId>,
    <R as frame_system::Config>::AccountId: Into<AccountId>,
    <R as frame_system::Config>::Event: From<pallet_balances::Event<R>>,
{
    fn on_nonzero_unbalanced(amount: NegativeImbalance<R>) {
        if let Some(author) = <pallet_authorship::Pallet<R>>::author() {
            <pallet_balances::Pallet<R>>::resolve_creating(&author, amount);
        }
    }
}

pub struct DealWithFees<R>(sp_std::marker::PhantomData<R>);
impl<R> OnUnbalanced<NegativeImbalance<R>> for DealWithFees<R>
where
    R: pallet_balances::Config + pallet_treasury::Config + pallet_authorship::Config,
    pallet_treasury::Pallet<R>: OnUnbalanced<NegativeImbalance<R>>,
    <R as frame_system::Config>::AccountId: From<AccountId>,
    <R as frame_system::Config>::AccountId: Into<AccountId>,
    <R as frame_system::Config>::Event: From<pallet_balances::Event<R>>,
{
    fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance<R>>) {
        if let Some(fees) = fees_then_tips.next() {
            // for fees, 75% to treasury, 25% to author
            let mut split = fees.ration(75, 25);
            if let Some(tips) = fees_then_tips.next() {
                // for tips, if any, 100% to author
                tips.merge_into(&mut split.1);
            }
            use pallet_treasury::Pallet as Treasury;
            <Treasury<R> as OnUnbalanced<_>>::on_unbalanced(split.0);
            <ToAuthor<R> as OnUnbalanced<_>>::on_unbalanced(split.1);
        }
    }
}

const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
/// We allow for 2 seconds of compute with a 6 second average block time.
pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND;
const WEIGHT_PER_GAS: u64 = 20_000;

pub struct ConstantFee<T>(sp_std::marker::PhantomData<T>);
impl<T> WeightToFeePolynomial for ConstantFee<T>
where
    T: BaseArithmetic + From<u32> + Copy + Unsigned + From<u64>,
{
    type Balance = T;

    fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
        let fee: u64 = (DOLLARS * 25).try_into().unwrap();
        smallvec!(WeightToFeeCoefficient {
            coeff_integer: fee.into(),
            coeff_frac: Perbill::zero(),
            negative: false,
            degree: 0,
        })
    }

    fn calc(_weight: &Weight) -> Self::Balance {
        let fee: u64 = (DOLLARS * 25).try_into().unwrap();
        return fee.into();
    }
}

parameter_types! {
    pub const TransactionByteFee: Balance = 1;
}

impl pallet_transaction_payment::Config for Runtime {
    type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees<Runtime>>;
    type OperationalFeeMultiplier = ConstU8<5>;
    type WeightToFee = ConstantFee<Balance>;
    type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
    
parameter_types! {
    pub const SpendPeriod: BlockNumber = 6 * DAYS;
    pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry");
    /// 5% of proposal value should be reserved from proposer balance,
    /// but not less than ProposalBondMinimum.
    /// This value would be slashed if proposal rejected.
    pub const ProposalBond: Permill = Permill::from_percent(0);
}

impl pallet_treasury::Config for Runtime {
    type Currency = Balances;
    // Only root for now, governance later.
    type ApproveOrigin = EnsureRoot<AccountId>;
    // Only root for now, governance later.
    type RejectOrigin = EnsureRoot<AccountId>;

    type Event = Event;
    // If proposal rejected - send deposit to treasury.
    type OnSlash = Treasury;
    type ProposalBond = ProposalBond;
    type ProposalBondMinimum = ();
    type ProposalBondMaximum = ();
    type SpendPeriod = SpendPeriod;
    // Not burning.
    type Burn = ();
    type PalletId = TreasuryPalletId;
    type BurnDestination = ();
    type WeightInfo = ();
    type SpendFunds = ();
    type MaxApprovals = ConstU32<100>;
}

parameter_types! {
    pub const UncleGenerations: BlockNumber = 5;
}

impl pallet_authorship::Config for Runtime {
    type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Aura>;
    type UncleGenerations = UncleGenerations;
    type FilterUncle = ();
    type EventHandler = ();
}
pub struct FindAuthorTruncated<F>(PhantomData<F>);
impl<F: FindAuthor<u32>> FindAuthor<H160> for FindAuthorTruncated<F> {
    fn find_author<'a, I>(digests: I) -> Option<H160>
    where
        I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
    {
        if let Some(author_index) = F::find_author(digests) {
            let authority_id = Aura::authorities()[author_index as usize].clone();
            return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));
        }
        None
    }
}

pub struct FixedGasWeightMapping;
impl GasWeightMapping for FixedGasWeightMapping {
    fn gas_to_weight(gas: u64) -> Weight {
        gas.saturating_mul(WEIGHT_PER_GAS)
    }
    fn weight_to_gas(weight: Weight) -> u64 {
        weight.wrapping_div(WEIGHT_PER_GAS)
    }
}

parameter_types! {
    pub const ChainId: u64 = 421;
    pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WEIGHT_PER_GAS);
    pub PrecompilesValue: FrontierPrecompiles<Runtime> = FrontierPrecompiles::<_>::new();
}

impl pallet_evm::Config for Runtime {
    type FeeCalculator = BaseFee;
    type GasWeightMapping = FixedGasWeightMapping;
    type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
    type CallOrigin = EnsureAddressTruncated;
    type WithdrawOrigin = EnsureAddressTruncated;
    type AddressMapping = HashedAddressMapping<BlakeTwo256>;
    type Currency = Balances;
    type Event = Event;
    type Runner = pallet_evm::runner::stack::Runner<Self>;
    type PrecompilesType = FrontierPrecompiles<Self>;
    type PrecompilesValue = PrecompilesValue;
    type ChainId = ChainId;
    type BlockGasLimit = BlockGasLimit;
    type OnChargeTransaction = EVMCurrencyAdapter<Balances, DealWithFees<Runtime>>;
    type FindAuthor = FindAuthorTruncated<Aura>;
}

impl pallet_ethereum::Config for Runtime {
    type Event = Event;
    type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;
}

frame_support::parameter_types! {
    pub BoundDivision: U256 = U256::from(1024);
}

impl pallet_dynamic_fee::Config for Runtime {
    type MinGasPriceBoundDivisor = BoundDivision;
}

frame_support::parameter_types! {
    pub IsActive: bool = false;
    pub DefaultBaseFeePerGas: U256 = U256::from(1_000_000_000);
}

pub struct BaseFeeThreshold;
impl pallet_base_fee::BaseFeeThreshold for BaseFeeThreshold {
    fn lower() -> Permill {
        Permill::zero()
    }
    fn ideal() -> Permill {
        Permill::from_parts(500_000)
    }
    fn upper() -> Permill {
        Permill::from_parts(1_000_000)
    }
}

impl pallet_base_fee::Config for Runtime {
    type Event = Event;
    type Threshold = BaseFeeThreshold;
    type IsActive = IsActive;
    type DefaultBaseFeePerGas = DefaultBaseFeePerGas;
}

impl pallet_hotfix_sufficients::Config for Runtime {
    type AddressMapping = HashedAddressMapping<BlakeTwo256>;
    type WeightInfo = ();
}

2
  • Did you solved the issue ?
    – lucgerrits
    Mar 10, 2023 at 14:51
  • 1
    Yes, we were not implementing a method in DealWithFees struct, which led to runtime using a default implementation that was empty, hence not having the desired affect Jun 2, 2023 at 8:28

1 Answer 1

1

Needed to implement this for DealWithFees as well

fn on_nonzero_unbalanced(amount: NegativeImbalance<R>) {}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.