Skip to content
Snippets Groups Projects
Select Git revision
  • dev
  • allow_nodejs_v10
  • sync
  • master
  • loki
  • test_prebuilt_nm
  • dependencies-caching
  • 1.6
  • 1302-migrating-from-wotb-c-to-wotb-rs-rust
  • feature/typage
  • OpenRC
  • RemoveFix
  • 1291-write-contributing-workflow
  • 1236-protocol-mediantime-computation-is-incorrect
  • 1287-npm-releases-are-not-updated-by-gitlab
  • 1283-build-release-for-linux-x86-in-docker
  • reduce_cpu
  • exp/ws2p-v2
  • rml10
  • 1.3
  • v1.7.0
  • v1.6.25
  • v1.6.24
  • v1.6.23
  • v1.6.22
  • v1.6.21
  • v1.6.20
  • v1.6.19
  • v1.6.18
  • v0.99.31
  • 0.99.30
  • v1.6.17
  • v1.6.16
  • v1.6.15
  • v0.99.27
  • v0.99.26
  • v0.99.25
  • v0.99.24
  • v0.99.23
  • v0.99.22
40 results

duniter.sh

Blame
  • Forked from nodes / typescript / duniter
    Source project has a limited visibility.
    fee_tests.rs 9.94 KiB
    // Copyright 2021 Axiom-Team
    //
    // This file is part of Duniter-v2S.
    //
    // Duniter-v2S is free software: you can redistribute it and/or modify
    // it under the terms of the GNU Affero General Public License as published by
    // the Free Software Foundation, version 3 of the License.
    //
    // Duniter-v2S is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    // GNU Affero General Public License for more details.
    //
    // You should have received a copy of the GNU Affero General Public License
    // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
    
    #![cfg(not(feature = "constant-fees"))]
    
    mod common;
    
    use common::*;
    use frame_support::{assert_ok, pallet_prelude::DispatchClass};
    use gdev_runtime::*;
    use sp_keyring::sr25519::Keyring;
    
    /// This test checks that an almost empty block incurs no fees for an extrinsic.
    #[test]
    fn test_fees_empty() {
        ExtBuilder::new(1, 3, 4)
            .with_initial_balances(vec![
                (Keyring::Alice.to_account_id(), 10_000),
                (Keyring::Eve.to_account_id(), 10_000),
            ])
            .build()
            .execute_with(|| {
                let call = RuntimeCall::Balances(BalancesCall::transfer_allow_death {
                    dest: Keyring::Eve.to_account_id().into(),
                    value: 500,
                });
    
                let xt = common::get_unchecked_extrinsic(call, 4u64, 8u64, Keyring::Alice, 0u64, 0u32);
                assert_ok!(Executive::apply_extrinsic(xt));
                // The block is almost empty, so the extrinsic should incur no fee
                assert_eq!(
                    Balances::free_balance(Keyring::Alice.to_account_id()),
                    10_000 - 500
                );
            })
    }
    
    /// This test checks the fee behavior when the block is almost full.
    /// - Multiple extrinsics are applied successfully without incurring fees until the block is under target weight.
    /// - The last extrinsic incurs additional fees as the block reaches its target, verifying fee calculation under high load conditions.
    #[test]
    fn test_fees_weight() {
        ExtBuilder::new(1, 3, 4)
            .with_initial_balances(vec![
                (Keyring::Alice.to_account_id(), 10_000),
                (Keyring::Eve.to_account_id(), 10_000),
            ])
            .build()
            .execute_with(|| {
                let weights = BlockWeights::get();
                let normal_max_weight = weights
                    .get(DispatchClass::Normal)
                    .max_total
                    .unwrap_or(weights.max_block);
    
                // Ensure that the next extrinsic is below the limit.
                System::set_block_consumed_resources(Weight::zero(), 0_usize);
    
                let call = RuntimeCall::System(SystemCall::remark {
                    remark: vec![255u8; 1],
                });
                let xt = get_unchecked_extrinsic(call, 4u64, 8u64, Keyring::Alice, 0u64, 0);
                assert_ok!(Executive::apply_extrinsic(xt));
                assert_eq!(
                    Balances::free_balance(Keyring::Alice.to_account_id()),
                    10_000
                );
    
                // Ensure that the next extrinsic exceeds the limit.
                System::set_block_consumed_resources(Target::get() * normal_max_weight, 0_usize);
                // The block will reach the fee limit, so the next extrinsic should start incurring fees.
                let call = RuntimeCall::System(SystemCall::remark {
                    remark: vec![255u8; 1],
                });
    
                let xt = get_unchecked_extrinsic(call, 4u64, 8u64, Keyring::Alice, 0u64, 1u32);
                assert_ok!(Executive::apply_extrinsic(xt));
                assert_ne!(
                    Balances::free_balance(Keyring::Alice.to_account_id()),
                    10_000
                );
            })
    }
    
    /// This test checks the fee behavior when the block is almost full.
    /// - Multiple extrinsics are applied successfully without incurring fees until the block is under target length.
    /// - The last extrinsic incurs additional fees as the block reaches its target, verifying fee calculation under high load conditions.
    #[test]
    fn test_fees_length() {
        ExtBuilder::new(1, 3, 4)
            .with_initial_balances(vec![
                (Keyring::Alice.to_account_id(), 10_000),
                (Keyring::Eve.to_account_id(), 10_000),
            ])
            .build()
            .execute_with(|| {
                let length = BlockLength::get();
                let normal_max_length = *length.max.get(DispatchClass::Normal) as u64;
    
                // Ensure that the next extrinsic is below the limit.
                System::set_block_consumed_resources(Weight::zero(), 0usize);
                let call = RuntimeCall::System(SystemCall::remark {
                    remark: vec![255u8; 100],
                });
                let xt = get_unchecked_extrinsic(call, 4u64, 8u64, Keyring::Alice, 0u64, 0u32);
                assert_ok!(Executive::apply_extrinsic(xt));
                assert_eq!(
                    Balances::free_balance(Keyring::Alice.to_account_id()),
                    10_000
                );
    
                // Ensure that the next extrinsic exceeds the extrinsic limit.
                System::set_block_consumed_resources(Weight::zero(), 0usize);
                let call = RuntimeCall::System(SystemCall::remark {
                    remark: vec![0u8; 147],
                });
                let xt = get_unchecked_extrinsic(call, 4u64, 8u64, Keyring::Alice, 0u64, 1u32);
                assert_ok!(Executive::apply_extrinsic(xt));
                assert_ne!(
                    Balances::free_balance(Keyring::Alice.to_account_id()),
                    10_000
                );
    
                // Ensure that the next extrinsic exceeds the block limit.
                System::set_block_consumed_resources(
                    Weight::zero(),
                    (Target::get() * normal_max_length).try_into().unwrap(),
                );
                // The block will reach the fee limit, so the next extrinsic should start incurring fees.
                let call = RuntimeCall::System(SystemCall::remark {
                    remark: vec![255u8; 1],
                });
    
                let xt = get_unchecked_extrinsic(call, 4u64, 8u64, Keyring::Eve, 0u64, 0u32);
                assert_ok!(Executive::apply_extrinsic(xt));
                assert_ne!(Balances::free_balance(Keyring::Eve.to_account_id()), 10_000);
            })
    }
    
    /// This test checks the behavior of the fee multiplier based on block weight
    /// and previous block weight.
    #[test]
    fn test_fees_multiplier_weight() {
        ExtBuilder::new(1, 3, 4)
            .with_initial_balances(vec![
                (Keyring::Alice.to_account_id(), 10_000),
                (Keyring::Eve.to_account_id(), 10_000),
            ])
            .build()
            .execute_with(|| {
                let weights = BlockWeights::get();
                let normal_max_weight = weights
                    .get(DispatchClass::Normal)
                    .max_total
                    .unwrap_or(weights.max_block);
    
                assert_eq!(
                    pallet_transaction_payment::Pallet::<Runtime>::next_fee_multiplier(),
                    1.into()
                );
                // If the block weight is over the target and the previous block was also over the target,
                // the fee multiplier is increased by one, up to the MaxMultiplier.
                let mut current = 0u128;
                for i in 1..20u128 {
                    System::set_block_consumed_resources(Target::get() * normal_max_weight, 0_usize);
                    run_to_block(i as u32);
                    current += 1;
                    assert_eq!(
                        pallet_transaction_payment::Pallet::<Runtime>::next_fee_multiplier(),
                        core::cmp::min(current.into(), MaxMultiplier::get())
                    );
                }
    
                // If the block weight is under the target and the previous block was also under the target,
                // the fee multiplier is decreased by one, down to the one.
                let mut current = 10u128;
                for i in 20..50u32 {
                    run_to_block(i);
                    current = current.saturating_sub(1).max(1u128);
                    assert_eq!(
                        pallet_transaction_payment::Pallet::<Runtime>::next_fee_multiplier(),
                        current.into()
                    );
                }
            })
    }
    
    /// This test checks the behavior of the fee multiplier based on block length
    /// and previous block length.
    #[test]
    fn test_fees_multiplier_length() {
        ExtBuilder::new(1, 3, 4)
            .with_initial_balances(vec![
                (Keyring::Alice.to_account_id(), 10_000),
                (Keyring::Eve.to_account_id(), 10_000),
            ])
            .build()
            .execute_with(|| {
                let length = BlockLength::get();
                let normal_max_length = *length.max.get(DispatchClass::Normal) as u64;
    
                assert_eq!(
                    pallet_transaction_payment::Pallet::<Runtime>::next_fee_multiplier(),
                    1.into()
                );
                // If the block weight is over the target and the previous block was also over the target,
                // the fee multiplier is increased by one, up to the MaxMultiplier.
                let mut current = 0u128;
                for i in 1..20u128 {
                    System::set_block_consumed_resources(
                        Weight::zero(),
                        (Target::get() * normal_max_length).try_into().unwrap(),
                    );
                    run_to_block(i as u32);
                    current += 1;
                    assert_eq!(
                        pallet_transaction_payment::Pallet::<Runtime>::next_fee_multiplier(),
                        core::cmp::min(current.into(), MaxMultiplier::get())
                    );
                }
    
                // If the block weight is under the target and the previous block was also under the target,
                // the fee multiplier is decreased by one, down to the one.
                let mut current = 10u128;
                for i in 20..50u32 {
                    run_to_block(i);
                    current = current.saturating_sub(1).max(1u128);
                    assert_eq!(
                        pallet_transaction_payment::Pallet::<Runtime>::next_fee_multiplier(),
                        current.into()
                    );
                }
            })
    }