Skip to content

Commit

Permalink
test: refine fee and tip handling logic for runtime tests
Browse files Browse the repository at this point in the history
  • Loading branch information
TarekkMA committed Jan 9, 2025
1 parent 4392ec1 commit 213b022
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 69 deletions.
52 changes: 32 additions & 20 deletions runtime/moonbase/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2797,52 +2797,64 @@ fn substrate_based_fees_zero_txn_costs_only_base_extrinsic() {
#[test]
fn deal_with_fees_handles_tip() {
use frame_support::traits::OnUnbalanced;
use moonbase_runtime::{DealWithSubstrateFeesAndTip, Treasury};
use moonriver_runtime::{DealWithSubstrateFeesAndTip, Treasury};

ExtBuilder::default().build().execute_with(|| {
// This test checks the functionality of the `DealWithSubstrateFeesAndTip` trait implementation in the runtime.
// It simulates a scenario where a fee and a tip are issued to an account and ensures that the
// treasury receives the correct amount (set by FeesTreasuryProportion), and the rest is burned.
//
// The test follows these steps: (Assuming FeesTreasuryProportion is set to 20%)
// 1. It issues a fee of 100 and a tip of 1000.
// 2. It checks the total supply before the fee and tip are dealt with, which should be 1_100.
// 3. It checks that the treasury's balance is initially 0.
// 4. It calls `DealWithSubstrateFeesAndTip::on_unbalanceds` with the fee and tip.
// 5. It checks that the treasury's balance is now 220 (20% of the fee and tip).
// 6. It checks that the total supply has decreased by 880 (80% of the fee and tip), indicating
// that this amount was burned.
set_parachain_inherent_data();
// This test validates the functionality of the `DealWithSubstrateFeesAndTip` trait implementation
// in the Moonriver runtime. It verifies that:
// - The correct proportion of the fee is sent to the treasury.
// - The remaining fee is burned (removed from the total supply).
// - The entire tip is sent to the block author.

// The test details:
// 1. Simulate issuing a `fee` of 100 and a `tip` of 1000.
// 2. Confirm the initial total supply is 1,100 (equal to the sum of the issued fee and tip).
// 3. Confirm the treasury's balance is initially 0.
// 4. Execute the `DealWithSubstrateFeesAndTip::on_unbalanceds` function with the `fee` and `tip`.
// 5. Validate that the treasury's balance has increased by 20% of the fee (based on FeesTreasuryProportion).
// 6. Validate that 80% of the fee is burned, and the total supply decreases accordingly.
// 7. Validate that the entire tip (100%) is sent to the block author (collator).

// Step 1: Issue the fee and tip amounts.
let fee = <pallet_balances::Pallet<Runtime> as frame_support::traits::fungible::Balanced<
AccountId,
>>::issue(100);
let tip = <pallet_balances::Pallet<Runtime> as frame_support::traits::fungible::Balanced<
AccountId,
>>::issue(1000);

// Step 2: Validate the initial supply and balances.
let total_supply_before = Balances::total_issuance();
let block_author = pallet_author_inherent::Pallet::<Runtime>::get();
let block_author_balance_before = Balances::free_balance(&block_author);
assert_eq!(total_supply_before, 1_100);
assert_eq!(Balances::free_balance(&Treasury::account_id()), 0);

// Step 3: Execute the fees handling logic.
DealWithSubstrateFeesAndTip::on_unbalanceds(vec![fee, tip].into_iter());

// Step 4: Compute the split between treasury and burned fees based on FeesTreasuryProportion (20%).
let treasury_proportion = dynamic_params::runtime_config::FeesTreasuryProportion::get();

let treasury_fee_part: Balance = treasury_proportion.mul_floor(100);
let burnt_fee_part: Balance = 100 - treasury_fee_part;
let treasury_tip_part: Balance = treasury_proportion.mul_floor(1000);
let burnt_tip_part: Balance = 1000 - treasury_tip_part;

// treasury should have received FeesTreasuryProportion
// Step 5: Validate the treasury received 20% of the fee.
assert_eq!(
Balances::free_balance(&Treasury::account_id()),
treasury_fee_part + treasury_tip_part
treasury_fee_part,
);

// verify the rest is burned
// Step 6: Verify that 80% of the fee was burned (removed from the total supply).
let total_supply_after = Balances::total_issuance();
assert_eq!(total_supply_before - total_supply_after, burnt_fee_part,);

// Step 7: Validate that the block author (collator) received 100% of the tip.
let block_author_balance_after = Balances::free_balance(&block_author);
assert_eq!(
total_supply_before - total_supply_after,
burnt_fee_part + burnt_tip_part
block_author_balance_after - block_author_balance_before,
1000,
);
});
}
Expand Down
52 changes: 32 additions & 20 deletions runtime/moonbeam/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2618,52 +2618,64 @@ fn removed_precompiles() {
#[test]
fn deal_with_fees_handles_tip() {
use frame_support::traits::OnUnbalanced;
use moonbeam_runtime::{DealWithSubstrateFeesAndTip, Treasury};
use moonriver_runtime::{DealWithSubstrateFeesAndTip, Treasury};

ExtBuilder::default().build().execute_with(|| {
// This test checks the functionality of the `DealWithSubstrateFeesAndTip` trait implementation in the runtime.
// It simulates a scenario where a fee and a tip are issued to an account and ensures that the
// treasury receives the correct amount (set by FeesTreasuryProportion), and the rest is burned.
//
// The test follows these steps: (Assuming FeesTreasuryProportion is set to 20%)
// 1. It issues a fee of 100 and a tip of 1000.
// 2. It checks the total supply before the fee and tip are dealt with, which should be 1_100.
// 3. It checks that the treasury's balance is initially 0.
// 4. It calls `DealWithSubstrateFeesAndTip::on_unbalanceds` with the fee and tip.
// 5. It checks that the treasury's balance is now 220 (20% of the fee and tip).
// 6. It checks that the total supply has decreased by 880 (80% of the fee and tip), indicating
// that this amount was burned.
set_parachain_inherent_data();
// This test validates the functionality of the `DealWithSubstrateFeesAndTip` trait implementation
// in the Moonriver runtime. It verifies that:
// - The correct proportion of the fee is sent to the treasury.
// - The remaining fee is burned (removed from the total supply).
// - The entire tip is sent to the block author.

// The test details:
// 1. Simulate issuing a `fee` of 100 and a `tip` of 1000.
// 2. Confirm the initial total supply is 1,100 (equal to the sum of the issued fee and tip).
// 3. Confirm the treasury's balance is initially 0.
// 4. Execute the `DealWithSubstrateFeesAndTip::on_unbalanceds` function with the `fee` and `tip`.
// 5. Validate that the treasury's balance has increased by 20% of the fee (based on FeesTreasuryProportion).
// 6. Validate that 80% of the fee is burned, and the total supply decreases accordingly.
// 7. Validate that the entire tip (100%) is sent to the block author (collator).

// Step 1: Issue the fee and tip amounts.
let fee = <pallet_balances::Pallet<Runtime> as frame_support::traits::fungible::Balanced<
AccountId,
>>::issue(100);
let tip = <pallet_balances::Pallet<Runtime> as frame_support::traits::fungible::Balanced<
AccountId,
>>::issue(1000);

// Step 2: Validate the initial supply and balances.
let total_supply_before = Balances::total_issuance();
let block_author = pallet_author_inherent::Pallet::<Runtime>::get();
let block_author_balance_before = Balances::free_balance(&block_author);
assert_eq!(total_supply_before, 1_100);
assert_eq!(Balances::free_balance(&Treasury::account_id()), 0);

// Step 3: Execute the fees handling logic.
DealWithSubstrateFeesAndTip::on_unbalanceds(vec![fee, tip].into_iter());

// Step 4: Compute the split between treasury and burned fees based on FeesTreasuryProportion (20%).
let treasury_proportion = dynamic_params::runtime_config::FeesTreasuryProportion::get();

let treasury_fee_part: Balance = treasury_proportion.mul_floor(100);
let burnt_fee_part: Balance = 100 - treasury_fee_part;
let treasury_tip_part: Balance = treasury_proportion.mul_floor(1000);
let burnt_tip_part: Balance = 1000 - treasury_tip_part;

// treasury should have received 20%
// Step 5: Validate the treasury received 20% of the fee.
assert_eq!(
Balances::free_balance(&Treasury::account_id()),
treasury_fee_part + treasury_tip_part
treasury_fee_part,
);

// verify 80% burned
// Step 6: Verify that 80% of the fee was burned (removed from the total supply).
let total_supply_after = Balances::total_issuance();
assert_eq!(total_supply_before - total_supply_after, burnt_fee_part,);

// Step 7: Validate that the block author (collator) received 100% of the tip.
let block_author_balance_after = Balances::free_balance(&block_author);
assert_eq!(
total_supply_before - total_supply_after,
burnt_fee_part + burnt_tip_part
block_author_balance_after - block_author_balance_before,
1000,
);
});
}
Expand Down
50 changes: 31 additions & 19 deletions runtime/moonriver/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2520,49 +2520,61 @@ fn deal_with_fees_handles_tip() {
use moonriver_runtime::{DealWithSubstrateFeesAndTip, Treasury};

ExtBuilder::default().build().execute_with(|| {
// This test checks the functionality of the `DealWithSubstrateFeesAndTip` trait implementation in the runtime.
// It simulates a scenario where a fee and a tip are issued to an account and ensures that the
// treasury receives the correct amount (set by FeesTreasuryProportion), and the rest is burned.
//
// The test follows these steps: (Assuming FeesTreasuryProportion is set to 20%)
// 1. It issues a fee of 100 and a tip of 1000.
// 2. It checks the total supply before the fee and tip are dealt with, which should be 1_100.
// 3. It checks that the treasury's balance is initially 0.
// 4. It calls `DealWithSubstrateFeesAndTip::on_unbalanceds` with the fee and tip.
// 5. It checks that the treasury's balance is now 220 (20% of the fee and tip).
// 6. It checks that the total supply has decreased by 880 (80% of the fee and tip), indicating
// that this amount was burned.
set_parachain_inherent_data();
// This test validates the functionality of the `DealWithSubstrateFeesAndTip` trait implementation
// in the Moonriver runtime. It verifies that:
// - The correct proportion of the fee is sent to the treasury.
// - The remaining fee is burned (removed from the total supply).
// - The entire tip is sent to the block author.

// The test details:
// 1. Simulate issuing a `fee` of 100 and a `tip` of 1000.
// 2. Confirm the initial total supply is 1,100 (equal to the sum of the issued fee and tip).
// 3. Confirm the treasury's balance is initially 0.
// 4. Execute the `DealWithSubstrateFeesAndTip::on_unbalanceds` function with the `fee` and `tip`.
// 5. Validate that the treasury's balance has increased by 20% of the fee (based on FeesTreasuryProportion).
// 6. Validate that 80% of the fee is burned, and the total supply decreases accordingly.
// 7. Validate that the entire tip (100%) is sent to the block author (collator).

// Step 1: Issue the fee and tip amounts.
let fee = <pallet_balances::Pallet<Runtime> as frame_support::traits::fungible::Balanced<
AccountId,
>>::issue(100);
let tip = <pallet_balances::Pallet<Runtime> as frame_support::traits::fungible::Balanced<
AccountId,
>>::issue(1000);

// Step 2: Validate the initial supply and balances.
let total_supply_before = Balances::total_issuance();
let block_author = pallet_author_inherent::Pallet::<Runtime>::get();
let block_author_balance_before = Balances::free_balance(&block_author);
assert_eq!(total_supply_before, 1_100);
assert_eq!(Balances::free_balance(&Treasury::account_id()), 0);

// Step 3: Execute the fees handling logic.
DealWithSubstrateFeesAndTip::on_unbalanceds(vec![fee, tip].into_iter());

// Step 4: Compute the split between treasury and burned fees based on FeesTreasuryProportion (20%).
let treasury_proportion = dynamic_params::runtime_config::FeesTreasuryProportion::get();

let treasury_fee_part: Balance = treasury_proportion.mul_floor(100);
let burnt_fee_part: Balance = 100 - treasury_fee_part;
let treasury_tip_part: Balance = treasury_proportion.mul_floor(1000);
let burnt_tip_part: Balance = 1000 - treasury_tip_part;

// treasury should have received 20%
// Step 5: Validate the treasury received 20% of the fee.
assert_eq!(
Balances::free_balance(&Treasury::account_id()),
treasury_fee_part + treasury_tip_part
treasury_fee_part,
);

// verify 80% burned
// Step 6: Verify that 80% of the fee was burned (removed from the total supply).
let total_supply_after = Balances::total_issuance();
assert_eq!(total_supply_before - total_supply_after, burnt_fee_part,);

// Step 7: Validate that the block author (collator) received 100% of the tip.
let block_author_balance_after = Balances::free_balance(&block_author);
assert_eq!(
total_supply_before - total_supply_after,
burnt_fee_part + burnt_tip_part
block_author_balance_after - block_author_balance_before,
1000,
);
});
}
Expand Down
7 changes: 2 additions & 5 deletions test/helpers/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,9 @@ export const verifyBlockFees = async (
feesTreasuryProportion,
fee.partialFee.toBigInt()
);
const tipPortions = calculateFeePortions(
feesTreasuryProportion,
extrinsic.tip.toBigInt()
);

txFees += fee.partialFee.toBigInt() + extrinsic.tip.toBigInt();
txBurnt += feePortions.burnt + tipPortions.burnt;
txBurnt += feePortions.burnt;

// verify entire substrate txn fee
const apiAt = await context.polkadotJs().at(previousBlockHash);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ describeSuite({
const issuanceBefore = (
await context.polkadotJs().query.balances.totalIssuance()
).toBigInt();
const collatorBalBefore = await context.viem().getBalance({ address: collatorAddress });

const { result } = await context.createBlock(
context
Expand All @@ -251,25 +252,36 @@ describeSuite({
const issuanceAfter = (
await context.polkadotJs().query.balances.totalIssuance()
).toBigInt();
const collatorBalAfter = await context.viem().getBalance({ address: collatorAddress });

const treasuryIncrease = balanceAfter - balanceBefore;
const issuanceDecrease = issuanceBefore - issuanceAfter;
const fee = extractFee(result?.events)!.amount.toBigInt();
const collatorIncrease = collatorBalAfter - collatorBalBefore;
const tipPaid = withTip ? t.tipAmount : 0n;
const feeWithoutTip = extractFee(result?.events)!.amount.toBigInt() - tipPaid;

expect(
treasuryIncrease + issuanceDecrease,
`Sum of TreasuryIncrease and IssuanceDecrease should be equal to the fees`
).to.equal(fee);
`Sum of TreasuryIncrease and IssuanceDecrease should be equal to the fees without tip`
).to.equal(feeWithoutTip);

expect(
treasuryIncrease,
`${treasuryPercentage}% of the fees should go to treasury`
).to.equal(calcTreasuryIncrease(fee, withTip ? t.tipAmount : undefined));
).to.equal(calcTreasuryIncrease(feeWithoutTip));

expect(issuanceDecrease, `${burnPercentage}% of the fees should be burned`).to.equal(
calcIssuanceDecrease(fee, withTip ? t.tipAmount : undefined)
calcIssuanceDecrease(feeWithoutTip)
);

if (withTip) {
expect(collatorIncrease, "100% of the tip should go to the collator").to.equal(
t.tipAmount
);
} else {
expect(collatorIncrease, "No tip should be paid to the collator").to.equal(0n);
}

await verifyLatestBlockFees(context, t.transfer_amount);
},
});
Expand Down

0 comments on commit 213b022

Please sign in to comment.