Skip to content
Snippets Groups Projects
Select Git revision
  • f8e7ad577ad73f864c376235b7f8bd359d3321b1
  • dev default protected
  • release/1.9.1 protected
  • pini-1.8-docker
  • pini-sync-onlypeers
  • duniter-v2s-issue-123-industrialize-releases
  • feature/build-aarch64-nodejs16
  • release/1.8 protected
  • pini-docker
  • ci_tags
  • fix/1448/1.8/txs_not_stored
  • feature/node-20
  • fix/1441/node_summary_with_storage
  • fix/1442/improve_bma_tx_history
  • feature/wotwizard-1.8
  • release/1.9 protected
  • 1.7 protected
  • feature/docker-set-latest protected
  • feature/fast-docker-build-1.8.4
  • fast-docker-build protected
  • feature/dump-distance
  • v1.8.7 protected
  • v1.8.7-rc4 protected
  • v1.8.7-rc3 protected
  • v1.8.7-rc2 protected
  • v1.8.7-rc1 protected
  • v1.8.6 protected
  • v1.7.23 protected
  • v1.8.5 protected
  • v1.8.4 protected
  • v1.8.3 protected
  • v1.8.2 protected
  • v1.8.1 protected
  • v1.8.0 protected
  • v1.8.0-rc1 protected
  • v1.8.0-beta5 protected
  • v1.8.0-beta4 protected
  • v1.8.0-beta3 protected
  • v1.8.0-beta2 protected
  • v1.8.0-beta protected
  • v1.7.21 protected
41 results

server.js

Blame
  • 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()
                    );
                }
            })
    }