From 5beb22f11636449a48aa19e4ee34794a9a67cc14 Mon Sep 17 00:00:00 2001 From: Uncle Stinky Date: Fri, 13 Jun 2025 16:42:14 +0300 Subject: [PATCH] avoid errors from minting sub-existential balance Signed-off-by: Uncle Stinky --- Cargo.lock | 6 ++--- pallets/slow-clap/Cargo.toml | 2 +- pallets/slow-clap/src/lib.rs | 27 ++++++++++----------- pallets/slow-clap/src/tests.rs | 44 ++++++++++++++++++++++++++++------ 4 files changed, 53 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c8f0ec..65b74b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3648,7 +3648,7 @@ dependencies = [ [[package]] name = "ghost-networks" -version = "0.1.5" +version = "0.1.6" dependencies = [ "frame-benchmarking", "frame-support", @@ -3834,7 +3834,7 @@ dependencies = [ [[package]] name = "ghost-slow-clap" -version = "0.3.23" +version = "0.3.24" dependencies = [ "frame-benchmarking", "frame-support", @@ -3870,7 +3870,7 @@ dependencies = [ [[package]] name = "ghost-traits" -version = "0.3.21" +version = "0.3.22" dependencies = [ "frame-support", "sp-runtime 31.0.1", diff --git a/pallets/slow-clap/Cargo.toml b/pallets/slow-clap/Cargo.toml index af39f50..e87e73f 100644 --- a/pallets/slow-clap/Cargo.toml +++ b/pallets/slow-clap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ghost-slow-clap" -version = "0.3.23" +version = "0.3.24" description = "Applause protocol for the EVM bridge" license.workspace = true authors.workspace = true diff --git a/pallets/slow-clap/src/lib.rs b/pallets/slow-clap/src/lib.rs index 317fe89..c001cfc 100644 --- a/pallets/slow-clap/src/lib.rs +++ b/pallets/slow-clap/src/lib.rs @@ -28,7 +28,7 @@ use sp_runtime::{ self as rt_offchain, HttpError, storage::{MutateStorageError, StorageRetrievalError, StorageValueRef}, }, - traits::{CheckedSub, BlockNumberProvider, Convert, Saturating}, + traits::{BlockNumberProvider, Convert, Saturating}, }; use sp_std::{ vec::Vec, prelude::*, @@ -330,6 +330,7 @@ pub mod pallet { UnregisteredClapRemove, TooMuchAuthorities, CouldNotAccumulateCommission, + CouldNotAccumulateIncomingImbalance, CouldNotIncreaseGatekeeperAmount, } @@ -580,25 +581,21 @@ impl Pallet { .map(|network_data| Perbill::from_parts(network_data.incoming_fee)) .unwrap_or_default() .mul_ceil(clap.amount); + let final_amount = clap.amount.saturating_sub(commission); - let final_amount = clap.amount - .checked_sub(&commission) - .map(|value| T::Currency::minimum_balance() - .lt(&value) - .then(|| value) - ) - .flatten() - .unwrap_or_default(); - - let _ = T::NetworkDataHandler::increase_gatekeeper_amount(&clap.network_id, &final_amount) + let _ = T::NetworkDataHandler::increase_gatekeeper_amount(&clap.network_id, &clap.amount) .map_err(|_| Error::::CouldNotIncreaseGatekeeperAmount)?; + let _ = T::NetworkDataHandler::accumulate_incoming_imbalance(&final_amount) + .map_err(|_| Error::::CouldNotAccumulateIncomingImbalance)?; let _ = T::NetworkDataHandler::accumulate_commission(&commission) .map_err(|_| Error::::CouldNotAccumulateCommission)?; - T::Currency::mint_into( - &clap.receiver, - final_amount - )?; + if final_amount > T::Currency::minimum_balance() { + T::Currency::mint_into( + &clap.receiver, + final_amount + )?; + } *is_applaused = true; diff --git a/pallets/slow-clap/src/tests.rs b/pallets/slow-clap/src/tests.rs index 5349b8b..7be3ca6 100644 --- a/pallets/slow-clap/src/tests.rs +++ b/pallets/slow-clap/src/tests.rs @@ -265,7 +265,7 @@ fn should_increase_gatkeeper_amount_accordingly() { assert_ok!(do_clap_from(session_index, network_id, 1, false)); assert_ok!(do_clap_from(session_index, network_id, 2, false)); - assert_eq!(Networks::gatekeeper_amount(network_id), amount.saturating_div(2)); + assert_eq!(Networks::gatekeeper_amount(network_id), amount); assert_eq!(Networks::bridged_imbalance().bridged_in, amount.saturating_div(2)); assert_eq!(Networks::bridged_imbalance().bridged_out, 0); }); @@ -594,7 +594,7 @@ fn should_throw_error_on_commission_overflow() { assert_ok!(SlowClap::slow_clap(RuntimeOrigin::none(), clap, signature)); } else { assert_err!(SlowClap::slow_clap(RuntimeOrigin::none(), clap, signature), - Error::::CouldNotIncreaseGatekeeperAmount); + Error::::CouldNotAccumulateIncomingImbalance); } } @@ -617,19 +617,19 @@ fn should_nullify_commission_on_finalize() { let (_, _, amount) = get_mocked_metadata(); new_test_ext().execute_with(|| { - let _ = prepare_evm_network(Some(network_id), Some(500_000_000)); + let _ = prepare_evm_network(Some(network_id), Some(1_000_000_000)); let session_index = advance_session_and_get_index(); assert_eq!(Networks::accumulated_commission(), 0); assert_ok!(do_clap_from(session_index, network_id, 0, false)); assert_ok!(do_clap_from(session_index, network_id, 1, false)); - assert_eq!(Networks::accumulated_commission(), amount.saturating_div(2)); + assert_eq!(Networks::accumulated_commission(), amount); assert_eq!(Networks::is_nullification_period(), false); assert_eq!(BridgedInflationCurve::::era_payout( total_staked, - (total_issuance + amount).into(), - 0), (1260099399952u128, 208739900600048u128)); // precomputed values + total_issuance, + 0), (420000000000000, 0)); // precomputed values assert_eq!(Networks::is_nullification_period(), true); Networks::on_finalize(System::block_number()); @@ -793,10 +793,40 @@ fn should_emit_event_on_each_clap_and_on_applause() { }); } +#[test] +fn should_not_fail_on_sub_existential_balance() { + let (network_id, transaction_hash, unique_transaction_hash) + = generate_unique_hash(None, None, None, None); + let (_, receiver, amount) = get_mocked_metadata(); + + new_test_ext().execute_with(|| { + let _ = prepare_evm_network(Some(network_id), Some(1_000_000_000)); // 100% + let session_index = advance_session_and_get_index(); + let received_claps_key = (session_index, transaction_hash, unique_transaction_hash); + + assert_eq!(Networks::accumulated_commission(), 0); + assert_eq!(Networks::gatekeeper_amount(network_id), 0); + assert_eq!(Networks::bridged_imbalance().bridged_in, 0); + assert_eq!(Networks::bridged_imbalance().bridged_out, 0); + assert_eq!(Balances::balance(&receiver), 0); + assert_eq!(SlowClap::applauses_for_transaction(&received_claps_key), false); + + assert_ok!(do_clap_from(session_index, network_id, 0, false)); + assert_ok!(do_clap_from(session_index, network_id, 1, false)); + assert_ok!(do_clap_from(session_index, network_id, 2, false)); + + assert_eq!(Networks::accumulated_commission(), amount); + assert_eq!(Networks::gatekeeper_amount(network_id), amount); + assert_eq!(Networks::bridged_imbalance().bridged_in, 0); + assert_eq!(Networks::bridged_imbalance().bridged_out, 0); + assert_eq!(Balances::balance(&receiver), 0); + assert_eq!(SlowClap::applauses_for_transaction(&received_claps_key), true); + }); +} + // TODO: multiple logs will create multiple records // TODO: errors should be checked as much as possible // TODO: offences generated as expected -// TODO: deal with below existential amount after commission fn advance_session_and_get_index() -> u32 { advance_session();