Comportement actuel des frais

Je ne comprends pas le comportement actuel des frais de transaction.

En théorie

Frais constants égaux à 1 :

impl WeightToFee
{
    fn weight_to_fee(_weight: &Weight) -> Self::Balance {
        // Force constant fees for now
        One::one()
    }
}

En pratique (tests end2end)

Frais constants égaux à 2 (cĞD) :

Feature: Balance transfer all
  Scenario: If bob sends all his ĞDs to Dave
    When bob sends all his ĞDs to dave
    """
    Bob is a member, as such he is not allowed to empty his account completely,
    if he tries to do so, the existence deposit (2 ĞD) must remain.
    """
    Then bob should have 2 ĞD
    """
    10 ĞD (initial Bob balance) - 2 ĞD (Existential deposit) - 0.02 ĞD (transaction fees)
    """
    Then dave should have 798 cĞD

En pratique (duniter --dev)

Quand je fais un balance.transfer() de Bob vers Charlie dans polkadotjs, il y a un frais de 1 prélevé, et envoyé à Alice (validateur).

(dans ma branche actuelle ça va à la trésorerie, mais c’est le même montant).

D’où peut bien venir cette différence de comportement ??

pallets_config.rs

impl pallet_transaction_payment::Config for Runtime {
    /* ... */
    #[cfg(not(feature = "runtime-benchmarks"))]
    type WeightToFee = common_runtime::fees::WeightToFeeImpl<Balance>;
    #[cfg(feature = "runtime-benchmarks")]
    type WeightToFee = frame_support::weights::ConstantMultiplier::<u64, sp_core::ConstU64<0u64>>;
    /* ... */
}

ce qui explique des comportements différents mais pas les frais de 2, qui devraient être à 0.

C’est normal de désactiver les frais pour les benchmarks (mais ça peut fausser nos mesures pour les quotas), par contre les tests end2end et mon test local utilisent le même binaire compilé avec les options par défaut, donc ça n’explique pas la différence.

Ah oui j’ai confondu… Le mystère reste entier.

De la variable DUNITER_GENESIS_CONFIG, qui ne paramètre pas le même Genesis dans le cas d’utilisation de --dev selon que la variable est définie ou non. Cf : Etat des lieux des différentes chaînes

C’est bien piégeux !

edit : ah ben non, c’est pas si évident, j’ai répondu intuitivement mais je ne vois pas où sont précisés les frais.

edit 2 : ou alors l’exécutable des tests end2end n’est pas le même que celui que tu utilises avec Polkadotjs :confused:

C’est dans le fichier runtime/common/src/fees.rs qui convertit les weight en fees. Et ensuite, c’est ce que disait tuxmain, c’est configuré dans runtime/common/src/pallets_config.rs. Mais donc il n’y a pas moyen d’avoir deux runtime avec des règles différentes.

Le binaire utilisé par les tests end2end est le même que celui que j’ai utilisé pour mes tests manuels.

// dans end2end-tests/tests/common/mod.rs
const DUNITER_LOCAL_PATH: &str = "../target/debug/duniter";

J’ai ajouté un test d’intégration sur les frais, lui aussi dit que les frais sont de 2.

/// test currency transfer with extrinsic
// the signer account should pay fees and a tip
// the treasury should get the fees
#[test]
fn test_transfer_xt() {
    ExtBuilder::new(1, 3, 4)
        .with_initial_balances(vec![
            (AccountKeyring::Alice.to_account_id(), 10_000),
            (AccountKeyring::Eve.to_account_id(), 10_000),
        ])
        .build()
        .execute_with(|| {
            let call = RuntimeCall::Balances(BalancesCall::transfer_allow_death {
                dest: AccountKeyring::Eve.to_account_id().into(),
                value: 500,
            });

            // 1 cĞD of tip
            let xt = get_unchecked_extrinsic(call, 4u64, 8u64, AccountKeyring::Alice, 1u64);
            let info = xt.get_dispatch_info();
            println!("dispatch info:\n\t {:?}\n", info);

            // nothing in treasury at start
            // FIXME treasury is initialized at ED
            assert_eq!(Balances::free_balance(Treasury::account_id()), 200);
            // Alice gives 500 to Eve
            assert_ok!(Executive::apply_extrinsic(xt));
            // check amounts
            assert_eq!(
                Balances::free_balance(AccountKeyring::Alice.to_account_id()),
                10_000 - 500 - 3 // initial - transfered - fees
            );
            assert_eq!(
                Balances::free_balance(AccountKeyring::Eve.to_account_id()),
                10_000 + 500 // initial + transfered
            );
            assert_eq!(Balances::free_balance(Treasury::account_id()), 203);
        })
}

J’ai mis du temps à y arriver parce que j’avais initialisé la trésorerie à zéro et que donc il ne pouvait pas recevoir les frais parce qu’il était en dessous du dépôt existentiel (cf Soldes des comptes au genesis v2 - #7 by HugoTrentesaux). Donc j’ai lu de long en large le code de substrate sur l’exécution d’un extrinsic (pallet-executive et primitives associées) et le paiement des frais de transaction (pallet-transaction-payment et toute la mécanique du imbalance…). Bref c’était long ><

Par contre, le test manuel donne toujours la même chose :

Et la trésorerie était dans tous les cas initialisée à 2 ĞD, il y a un conflit entre balances et duniter-account je crois.

image