Skip to content
34 changes: 26 additions & 8 deletions runtime/moonbase/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ use frame_support::{
},
weights::{
constants::{RocksDbWeight, WEIGHT_PER_SECOND},
ConstantMultiplier, DispatchClass, GetDispatchInfo, IdentityFee, Weight,
WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial,
DispatchClass, GetDispatchInfo, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients,
WeightToFeePolynomial,
},
PalletId,
};
Expand Down Expand Up @@ -129,7 +129,7 @@ pub mod currency {
pub const UNIT: Balance = 1_000_000_000_000_000_000;
pub const KILOUNIT: Balance = 1_000_000_000_000_000_000_000;

pub const TRANSACTION_BYTE_FEE: Balance = 10 * MICROUNIT * SUPPLY_FACTOR;
pub const TRANSACTION_BYTE_FEE: Balance = 1 * GIGAWEI * SUPPLY_FACTOR;
pub const STORAGE_BYTE_FEE: Balance = 100 * MICROUNIT * SUPPLY_FACTOR;
pub const WEIGHT_FEE: Balance = 50 * KILOWEI * SUPPLY_FACTOR;

Expand Down Expand Up @@ -322,15 +322,33 @@ impl WeightToFeePolynomial for WeightToFee {
}
}

parameter_types! {
pub const TransactionByteFee: Balance = currency::TRANSACTION_BYTE_FEE;
pub struct LengthToFee;
impl WeightToFeePolynomial for LengthToFee {
type Balance = Balance;

fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
smallvec![
WeightToFeeCoefficient {
degree: 1,
coeff_frac: Perbill::zero(),
coeff_integer: currency::TRANSACTION_BYTE_FEE,
negative: false,
},
WeightToFeeCoefficient {
degree: 3,
coeff_frac: Perbill::zero(),
coeff_integer: 1,
negative: false,
},
]
}
}

impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees<Runtime>>;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee = IdentityFee<Balance>;
type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
type WeightToFee = WeightToFee;
type LengthToFee = LengthToFee;
type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Runtime>;
}

Expand Down Expand Up @@ -1373,7 +1391,7 @@ mod tests {
assert_eq!(SUPPLY_FACTOR, 1);

// txn fees
assert_eq!(TRANSACTION_BYTE_FEE, Balance::from(10 * MICROUNIT));
assert_eq!(TRANSACTION_BYTE_FEE, Balance::from(1 * GIGAWEI));
assert_eq!(
get!(pallet_transaction_payment, OperationalFeeMultiplier, u8),
5_u8
Expand Down
54 changes: 53 additions & 1 deletion runtime/moonbase/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use frame_support::{
StorageHasher, Twox128,
};
use moonbase_runtime::{
asset_config::AssetRegistrarMetadata, asset_config::LocalAssetInstance, currency::UNIT, get,
asset_config::AssetRegistrarMetadata, asset_config::LocalAssetInstance, get,
xcm_config::AssetType, AccountId, AssetId, AssetManager, Assets, Balances, BaseFee,
BlockWeights, Call, CrowdloanRewards, Event, LocalAssets, ParachainStaking, PolkadotXcm,
Precompiles, Runtime, System, XTokens, XcmTransactor, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX,
Expand Down Expand Up @@ -2299,6 +2299,58 @@ where
});
}

#[test]
#[rustfmt::skip]
fn length_fee_is_sensible() {
use sp_runtime::testing::TestXt;

ExtBuilder::default()
.with_balances(vec![
(AccountId::from(ALICE), (1 * UNIT) + (1 * WEI)),
(AccountId::from(BOB), 0),
])
.build()
.execute_with(|| {
// Substrate transfer
assert_ok!(Balances::transfer(
origin_of(AccountId::from(ALICE)),
AccountId::from(BOB),
1 * UNIT,
));
// 1 WEI is left in the account
assert_eq!(Balances::free_balance(AccountId::from(ALICE)), 1 * WEI);
});

// tests that length fee is sensible for a few hypothetical transactions
ExtBuilder::default().build().execute_with(|| {
let call = frame_system::Call::remark::<Runtime> { remark: vec![] };
let uxt: TestXt<_, ()> = TestXt::new(call, Some((1u64, ())));

let calc_fee = |len: u32| -> Balance {
moonbase_runtime::TransactionPayment::query_fee_details(uxt.clone(), len)
.inclusion_fee
.expect("fee should be calculated")
.len_fee
};

// editorconfig-checker-disable
// left: cost of length fee, right: size in bytes
// /------------- proportional component: O(N * 1B)
// | /- exponential component: O(N ** 3)
// | |
assert_eq!( 1_000_000_001, calc_fee(1));
assert_eq!( 10_000_001_000, calc_fee(10));
assert_eq!( 100_001_000_000, calc_fee(100));
assert_eq!( 1_001_000_000_000, calc_fee(1_000));
assert_eq!( 11_000_000_000_000, calc_fee(10_000)); // inflection point
assert_eq!( 1_100_000_000_000_000, calc_fee(100_000));
assert_eq!( 1_001_000_000_000_000_000, calc_fee(1_000_000)); // one UNIT, ~ 1MB
assert_eq!( 1_000_010_000_000_000_000_000, calc_fee(10_000_000));
assert_eq!(1_000_000_100_000_000_000_000_000, calc_fee(100_000_000));
Comment on lines +2337 to +2349
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the initial results

// editorconfig-checker-enable
});
}

#[test]
fn multiplier_can_grow_from_zero() {
let minimum_multiplier = moonbase_runtime::MinimumMultiplier::get();
Expand Down
4 changes: 2 additions & 2 deletions tests/tests/test-author-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describeDevMoonbeam("Author Mapping - simple association", (context) => {
expect((await getMappingInfo(context, bobAuthorId)).account).to.eq(ALITH);
expect(
((await context.polkadotApi.query.system.account(ALITH)) as any).data.free.toBigInt()
).to.eq(1207725818354628664997176n);
).to.eq(1207725819589017722705800n);
expect(
((await context.polkadotApi.query.system.account(ALITH)) as any).data.reserved.toBigInt()
).to.eq(2n * DEFAULT_GENESIS_MAPPING + DEFAULT_GENESIS_STAKING);
Expand All @@ -95,7 +95,7 @@ describeDevMoonbeam("Author Mapping - Fail to reassociate alice", (context) => {
//check state
expect(
((await context.polkadotApi.query.system.account(BALTATHAR)) as any).data.free.toBigInt()
).to.eq(1208925818354628664997176n);
).to.eq(1208925819589017722705800n);
expect(
((await context.polkadotApi.query.system.account(BALTATHAR)) as any).data.reserved.toBigInt()
).to.eq(0n);
Expand Down