Skip to content

Commit 614aa31

Browse files
authored
Implements a variable deposit base calculation for EPM signed submissions (#1547)
**Note**: This is a lift-and-shift PR from the old substrate and polkadot repos, both PRs have been reviewed and audited (paritytech/substrate#13983, paritytech/polkadot#7140) --- This PR implements a generic `BaseDeposit` calculation for signed submissions, based on the size of the submission queue. It adds a new associated type to EPM's config, `type SignedDepositBase`, that implements `Convert<usize, BalanceOf<T>>`, which is used to calculate the base deposit for signed submissions based on the size of the signed submissions queue. `struct GeometricDepositBase<Balance, Fixed, Inc>` implements the convert trait so that the deposit value increases as a geometric progression. The deposit base is calculated by `deposit_base = fixed_deposit_base * (1 + increase_factor)^n`, where `n` is the term of the progression (i.e. the number of signed submissions in the queue). `Fixed` and `Inc` generic params are getters for `Balance` and `IncreaseFactor` to compute the geometric progression. If `IncreaseFactor = 0`, then the signed deposit is constant and equal to `Fixed` regardless of the size of the queue. ### Runtime configs In Kusama, the progression with 10% increase without changing the current signed fixed deposit is: (term == size of the queue) Term 1: `1,333,333,332,000` Term 2: `1,333,333,332,000 * 1.10 = 1,466,666,665,200` Term 3: `1,333,333,332,000 * 1.10^2 = 1,613,333,331,200` Term 4: `1,333,333,332,000 * 1.10^3 = 1,774,666,664,320` Term 5: `1,333,333,332,000 * 1.10^4 = 1,952,133,330,752` Term 6: `1,333,333,332,000 * 1.10^5 = 2,147,346,663,827.20` Term 7: `1,333,333,332,000 * 1.10^6 = 2,362,081,330,210.92` Term 8: `1,333,333,332,000 * 1.10^7 = 2,598,289,463,231.01` Term 9: `1,333,333,332,000 * 1.10^8 = 2,858,118,409,554.11` Term 10: `1,333,333,332,000 * 1.10^9 = 3,143,930,250,509.52` Westend: Term 1: `2,000,000,000,000` Term 2: `2,000,000,000,000 * 1.10 = 2,200,000,000,000` Term 3: `2,000,000,000,000 * 1.10^2 = 2,420,000,000,000` Term 4: `2,000,000,000,000 * 1.10^3 = 2,662,000,000,000` Term 5: `2,000,000,000,000 * 1.10^4 = 2,928,200,000,000` Term 6: `2,000,000,000,000 * 1.10^5 = 3,221,020,000,000` Term 7: `2,000,000,000,000 * 1.10^6 = 3,543,122,000,000` Term 8: `2,000,000,000,000 * 1.10^7 = 3,897,434,200,000` Term 9: `2,000,000,000,000 * 1.10^8 = 4,287,177,620,000` Term 10: `2,000,000,000,000 * 1.10^9 = 4,715,895,382,000` and in Polkadot, the deposit increase is disabled in the current state of the PR, as the increase factor is 0% -- so nothing changes from the current behaviour. Closes https://github.com/paritytech-secops/srlabs_findings/issues/189
1 parent d569e72 commit 614aa31

8 files changed

Lines changed: 150 additions & 34 deletions

File tree

polkadot/runtime/kusama/src/lib.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ use xcm::latest::Junction;
9393

9494
pub use frame_system::Call as SystemCall;
9595
pub use pallet_balances::Call as BalancesCall;
96-
pub use pallet_election_provider_multi_phase::Call as EPMCall;
96+
pub use pallet_election_provider_multi_phase::{Call as EPMCall, GeometricDepositBase};
9797
#[cfg(feature = "std")]
9898
pub use pallet_staking::StakerStatus;
9999
use pallet_staking::UseValidatorsMap;
@@ -511,7 +511,8 @@ parameter_types! {
511511
// signed config
512512
pub const SignedMaxSubmissions: u32 = 16;
513513
pub const SignedMaxRefunds: u32 = 16 / 4;
514-
pub const SignedDepositBase: Balance = deposit(2, 0);
514+
pub const SignedFixedDeposit: Balance = deposit(2, 0);
515+
pub const SignedDepositIncreaseFactor: Percent = Percent::from_percent(10);
515516
pub const SignedDepositByte: Balance = deposit(0, 10) / 1024;
516517
// Each good submission will get 1/10 KSM as reward
517518
pub SignedRewardBase: Balance = UNITS / 10;
@@ -584,7 +585,8 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
584585
type SignedMaxSubmissions = SignedMaxSubmissions;
585586
type SignedMaxRefunds = SignedMaxRefunds;
586587
type SignedRewardBase = SignedRewardBase;
587-
type SignedDepositBase = SignedDepositBase;
588+
type SignedDepositBase =
589+
GeometricDepositBase<Balance, SignedFixedDeposit, SignedDepositIncreaseFactor>;
588590
type SignedDepositByte = SignedDepositByte;
589591
type SignedDepositWeight = ();
590592
type SignedMaxWeight =
@@ -2484,7 +2486,7 @@ mod fees_tests {
24842486
fn signed_deposit_is_sensible() {
24852487
// ensure this number does not change, or that it is checked after each change.
24862488
// a 1 MB solution should need around 0.16 KSM deposit
2487-
let deposit = SignedDepositBase::get() + (SignedDepositByte::get() * 1024 * 1024);
2489+
let deposit = SignedFixedDeposit::get() + (SignedDepositByte::get() * 1024 * 1024);
24882490
assert_eq_error_rate!(deposit, UNITS * 167 / 100, UNITS / 100);
24892491
}
24902492
}

polkadot/runtime/polkadot/src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ use xcm::latest::Junction;
9090

9191
pub use frame_system::Call as SystemCall;
9292
pub use pallet_balances::Call as BalancesCall;
93-
pub use pallet_election_provider_multi_phase::Call as EPMCall;
93+
pub use pallet_election_provider_multi_phase::{Call as EPMCall, GeometricDepositBase};
9494
#[cfg(feature = "std")]
9595
pub use pallet_staking::StakerStatus;
9696
use pallet_staking::UseValidatorsMap;
@@ -382,6 +382,8 @@ parameter_types! {
382382
// signed config
383383
pub const SignedMaxSubmissions: u32 = 16;
384384
pub const SignedMaxRefunds: u32 = 16 / 4;
385+
pub const SignedFixedDeposit: Balance = deposit(2, 0);
386+
pub const SignedDepositIncreaseFactor: Percent = Percent::from_percent(10);
385387
// 40 DOTs fixed deposit..
386388
pub const SignedDepositBase: Balance = deposit(2, 0);
387389
// 0.01 DOT per KB of solution data.
@@ -456,7 +458,8 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
456458
type SignedMaxSubmissions = SignedMaxSubmissions;
457459
type SignedMaxRefunds = SignedMaxRefunds;
458460
type SignedRewardBase = SignedRewardBase;
459-
type SignedDepositBase = SignedDepositBase;
461+
type SignedDepositBase =
462+
GeometricDepositBase<Balance, SignedFixedDeposit, SignedDepositIncreaseFactor>;
460463
type SignedDepositByte = SignedDepositByte;
461464
type SignedDepositWeight = ();
462465
type SignedMaxWeight =
@@ -2352,7 +2355,7 @@ mod test_fees {
23522355
fn signed_deposit_is_sensible() {
23532356
// ensure this number does not change, or that it is checked after each change.
23542357
// a 1 MB solution should take (40 + 10) DOTs of deposit.
2355-
let deposit = SignedDepositBase::get() + (SignedDepositByte::get() * 1024 * 1024);
2358+
let deposit = SignedFixedDeposit::get() + (SignedDepositByte::get() * 1024 * 1024);
23562359
assert_eq_error_rate!(deposit, 50 * DOLLARS, DOLLARS);
23572360
}
23582361
}

polkadot/runtime/westend/src/lib.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ use sp_runtime::{
7979
Keccak256, OpaqueKeys, SaturatedConversion, Verify,
8080
},
8181
transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity},
82-
ApplyExtrinsicResult, FixedU128, KeyTypeId, Perbill,
82+
ApplyExtrinsicResult, FixedU128, KeyTypeId, Perbill, Percent,
8383
};
8484
use sp_staking::SessionIndex;
8585
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
@@ -90,7 +90,7 @@ use xcm::latest::Junction;
9090

9191
pub use frame_system::Call as SystemCall;
9292
pub use pallet_balances::Call as BalancesCall;
93-
pub use pallet_election_provider_multi_phase::Call as EPMCall;
93+
pub use pallet_election_provider_multi_phase::{Call as EPMCall, GeometricDepositBase};
9494
#[cfg(feature = "std")]
9595
pub use pallet_staking::StakerStatus;
9696
use pallet_staking::UseValidatorsMap;
@@ -481,7 +481,8 @@ parameter_types! {
481481
// signed config
482482
pub const SignedMaxSubmissions: u32 = 128;
483483
pub const SignedMaxRefunds: u32 = 128 / 4;
484-
pub const SignedDepositBase: Balance = deposit(2, 0);
484+
pub const SignedFixedDeposit: Balance = deposit(2, 0);
485+
pub const SignedDepositIncreaseFactor: Percent = Percent::from_percent(10);
485486
pub const SignedDepositByte: Balance = deposit(0, 10) / 1024;
486487
// Each good submission will get 1 WND as reward
487488
pub SignedRewardBase: Balance = 1 * UNITS;
@@ -553,7 +554,8 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
553554
type SignedMaxSubmissions = SignedMaxSubmissions;
554555
type SignedMaxRefunds = SignedMaxRefunds;
555556
type SignedRewardBase = SignedRewardBase;
556-
type SignedDepositBase = SignedDepositBase;
557+
type SignedDepositBase =
558+
GeometricDepositBase<Balance, SignedFixedDeposit, SignedDepositIncreaseFactor>;
557559
type SignedDepositByte = SignedDepositByte;
558560
type SignedDepositWeight = ();
559561
type SignedMaxWeight =

substrate/bin/node/runtime/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub use node_primitives::{AccountId, Signature};
5858
use node_primitives::{AccountIndex, Balance, BlockNumber, Hash, Moment, Nonce};
5959
use pallet_asset_conversion::{NativeOrAssetId, NativeOrAssetIdConverter};
6060
use pallet_broker::{CoreAssignment, CoreIndex, CoretimeInterface, PartsOf57600};
61-
use pallet_election_provider_multi_phase::SolutionAccuracyOf;
61+
use pallet_election_provider_multi_phase::{GeometricDepositBase, SolutionAccuracyOf};
6262
use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
6363
use pallet_nfts::PalletFeatures;
6464
use pallet_nis::WithMaximumOf;
@@ -694,7 +694,8 @@ parameter_types! {
694694

695695
// signed config
696696
pub const SignedRewardBase: Balance = 1 * DOLLARS;
697-
pub const SignedDepositBase: Balance = 1 * DOLLARS;
697+
pub const SignedFixedDeposit: Balance = 1 * DOLLARS;
698+
pub const SignedDepositIncreaseFactor: Percent = Percent::from_percent(10);
698699
pub const SignedDepositByte: Balance = 1 * CENTS;
699700

700701
pub BetterUnsignedThreshold: Perbill = Perbill::from_rational(1u32, 10_000);
@@ -822,7 +823,8 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
822823
type MinerConfig = Self;
823824
type SignedMaxSubmissions = ConstU32<10>;
824825
type SignedRewardBase = SignedRewardBase;
825-
type SignedDepositBase = SignedDepositBase;
826+
type SignedDepositBase =
827+
GeometricDepositBase<Balance, SignedFixedDeposit, SignedDepositIncreaseFactor>;
826828
type SignedDepositByte = SignedDepositByte;
827829
type SignedMaxRefunds = ConstU32<3>;
828830
type SignedDepositWeight = ();

substrate/frame/election-provider-multi-phase/src/lib.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ use unsigned::VoterOf;
279279
pub use weights::WeightInfo;
280280

281281
pub use signed::{
282-
BalanceOf, NegativeImbalanceOf, PositiveImbalanceOf, SignedSubmission, SignedSubmissionOf,
283-
SignedSubmissions, SubmissionIndicesOf,
282+
BalanceOf, GeometricDepositBase, NegativeImbalanceOf, PositiveImbalanceOf, SignedSubmission,
283+
SignedSubmissionOf, SignedSubmissions, SubmissionIndicesOf,
284284
};
285285
pub use unsigned::{Miner, MinerConfig};
286286

@@ -572,6 +572,7 @@ pub mod pallet {
572572
use frame_election_provider_support::{InstantElectionProvider, NposSolver};
573573
use frame_support::{pallet_prelude::*, traits::EstimateCallFee};
574574
use frame_system::pallet_prelude::*;
575+
use sp_runtime::traits::Convert;
575576

576577
#[pallet::config]
577578
pub trait Config: frame_system::Config + SendTransactionTypes<Call<Self>> {
@@ -649,10 +650,6 @@ pub mod pallet {
649650
#[pallet::constant]
650651
type SignedRewardBase: Get<BalanceOf<Self>>;
651652

652-
/// Base deposit for a signed solution.
653-
#[pallet::constant]
654-
type SignedDepositBase: Get<BalanceOf<Self>>;
655-
656653
/// Per-byte deposit for a signed solution.
657654
#[pallet::constant]
658655
type SignedDepositByte: Get<BalanceOf<Self>>;
@@ -668,6 +665,10 @@ pub mod pallet {
668665
#[pallet::constant]
669666
type MaxWinners: Get<u32>;
670667

668+
/// Something that calculates the signed deposit base based on the signed submissions queue
669+
/// size.
670+
type SignedDepositBase: Convert<usize, BalanceOf<Self>>;
671+
671672
/// The maximum number of electing voters and electable targets to put in the snapshot.
672673
/// At the moment, snapshots are only over a single block, but once multi-block elections
673674
/// are introduced they will take place over multiple blocks.

substrate/frame/election-provider-multi-phase/src/mock.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
// limitations under the License.
1717

1818
use super::*;
19-
use crate::{self as multi_phase, unsigned::MinerConfig};
19+
use crate::{self as multi_phase, signed::GeometricDepositBase, unsigned::MinerConfig};
2020
use frame_election_provider_support::{
2121
bounds::{DataProviderBounds, ElectionBounds},
2222
data_provider, onchain, ElectionDataProvider, NposSolution, SequentialPhragmen,
@@ -44,8 +44,8 @@ use sp_npos_elections::{
4444
use sp_runtime::{
4545
bounded_vec,
4646
testing::Header,
47-
traits::{BlakeTwo256, IdentityLookup},
48-
BuildStorage, PerU16,
47+
traits::{BlakeTwo256, Convert, IdentityLookup},
48+
BuildStorage, PerU16, Percent,
4949
};
5050
use std::sync::Arc;
5151

@@ -283,7 +283,11 @@ parameter_types! {
283283
pub static UnsignedPhase: BlockNumber = 5;
284284
pub static SignedMaxSubmissions: u32 = 5;
285285
pub static SignedMaxRefunds: u32 = 1;
286-
pub static SignedDepositBase: Balance = 5;
286+
// for tests only. if `EnableVariableDepositBase` is true, the deposit base will be calculated
287+
// by `Multiphase::DepositBase`. Otherwise the deposit base is `SignedFixedDeposit`.
288+
pub static EnableVariableDepositBase: bool = false;
289+
pub static SignedFixedDeposit: Balance = 5;
290+
pub static SignedDepositIncreaseFactor: Percent = Percent::from_percent(10);
287291
pub static SignedDepositByte: Balance = 0;
288292
pub static SignedDepositWeight: Balance = 0;
289293
pub static SignedRewardBase: Balance = 7;
@@ -393,7 +397,7 @@ impl crate::Config for Runtime {
393397
type OffchainRepeat = OffchainRepeat;
394398
type MinerTxPriority = MinerTxPriority;
395399
type SignedRewardBase = SignedRewardBase;
396-
type SignedDepositBase = SignedDepositBase;
400+
type SignedDepositBase = Self;
397401
type SignedDepositByte = ();
398402
type SignedDepositWeight = ();
399403
type SignedMaxWeight = SignedMaxWeight;
@@ -414,6 +418,18 @@ impl crate::Config for Runtime {
414418
type ElectionBounds = ElectionsBounds;
415419
}
416420

421+
impl Convert<usize, BalanceOf<Runtime>> for Runtime {
422+
/// returns the geometric increase deposit fee if `EnableVariableDepositBase` is set, otherwise
423+
/// the fee is `SignedFixedDeposit`.
424+
fn convert(queue_len: usize) -> Balance {
425+
if !EnableVariableDepositBase::get() {
426+
SignedFixedDeposit::get()
427+
} else {
428+
GeometricDepositBase::<Balance, SignedFixedDeposit, SignedDepositIncreaseFactor>::convert(queue_len)
429+
}
430+
}
431+
}
432+
417433
impl<LocalCall> frame_system::offchain::SendTransactionTypes<LocalCall> for Runtime
418434
where
419435
RuntimeCall: From<LocalCall>,
@@ -553,8 +569,14 @@ impl ExtBuilder {
553569
<SignedMaxSubmissions>::set(count);
554570
self
555571
}
572+
pub fn signed_base_deposit(self, base: u64, variable: bool, increase: Percent) -> Self {
573+
<EnableVariableDepositBase>::set(variable);
574+
<SignedFixedDeposit>::set(base);
575+
<SignedDepositIncreaseFactor>::set(increase);
576+
self
577+
}
556578
pub fn signed_deposit(self, base: u64, byte: u64, weight: u64) -> Self {
557-
<SignedDepositBase>::set(base);
579+
<SignedFixedDeposit>::set(base);
558580
<SignedDepositByte>::set(byte);
559581
<SignedDepositWeight>::set(weight);
560582
self

substrate/frame/election-provider-multi-phase/src/signed.rs

Lines changed: 84 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
//! The signed phase implementation.
1919
20+
use core::marker::PhantomData;
21+
2022
use crate::{
2123
unsigned::MinerConfig, Config, ElectionCompute, Pallet, QueuedSolution, RawSolution,
2224
ReadySolution, SignedSubmissionIndices, SignedSubmissionNextIndex, SignedSubmissionsMap,
@@ -32,8 +34,8 @@ use sp_arithmetic::traits::SaturatedConversion;
3234
use sp_core::bounded::BoundedVec;
3335
use sp_npos_elections::ElectionScore;
3436
use sp_runtime::{
35-
traits::{Saturating, Zero},
36-
RuntimeDebug,
37+
traits::{Convert, Saturating, Zero},
38+
FixedPointNumber, FixedPointOperand, FixedU128, Percent, RuntimeDebug,
3739
};
3840
use sp_std::{
3941
cmp::Ordering,
@@ -348,6 +350,32 @@ impl<T: Config> SignedSubmissions<T> {
348350
}
349351
}
350352

353+
/// Type that can be used to calculate the deposit base for signed submissions.
354+
///
355+
/// The deposit base is calculated as a geometric progression based on the number of signed
356+
/// submissions in the queue. The size of the queue represents the progression term.
357+
pub struct GeometricDepositBase<Balance, Fixed, Inc> {
358+
_marker: (PhantomData<Balance>, PhantomData<Fixed>, PhantomData<Inc>),
359+
}
360+
361+
impl<Balance, Fixed, Inc> Convert<usize, Balance> for GeometricDepositBase<Balance, Fixed, Inc>
362+
where
363+
Balance: FixedPointOperand,
364+
Fixed: Get<Balance>,
365+
Inc: Get<Percent>,
366+
{
367+
// Calculates the base deposit as a geometric progression based on the number of signed
368+
// submissions.
369+
//
370+
// The nth term is obtained by calculating `base * (1 + increase_factor)^nth`. Example: factor
371+
// 5, with initial deposit of 1000 and 10% of increase factor is 1000 * (1 + 0.1)^5.
372+
fn convert(queue_len: usize) -> Balance {
373+
let increase_factor: FixedU128 = FixedU128::from_u32(1) + Inc::get().into();
374+
375+
increase_factor.saturating_pow(queue_len).saturating_mul_int(Fixed::get())
376+
}
377+
}
378+
351379
impl<T: Config> Pallet<T> {
352380
/// `Self` accessor for `SignedSubmission<T>`.
353381
pub fn signed_submissions() -> SignedSubmissions<T> {
@@ -520,14 +548,14 @@ impl<T: Config> Pallet<T> {
520548
size: SolutionOrSnapshotSize,
521549
) -> BalanceOf<T> {
522550
let encoded_len: u32 = raw_solution.encoded_size().saturated_into();
523-
let encoded_len: BalanceOf<T> = encoded_len.into();
551+
let encoded_len_balance: BalanceOf<T> = encoded_len.into();
524552
let feasibility_weight = Self::solution_weight_of(raw_solution, size);
525553

526-
let len_deposit = T::SignedDepositByte::get().saturating_mul(encoded_len);
554+
let len_deposit = T::SignedDepositByte::get().saturating_mul(encoded_len_balance);
527555
let weight_deposit = T::SignedDepositWeight::get()
528556
.saturating_mul(feasibility_weight.ref_time().saturated_into());
529557

530-
T::SignedDepositBase::get()
558+
T::SignedDepositBase::convert(Self::signed_submissions().len())
531559
.saturating_add(len_deposit)
532560
.saturating_add(weight_deposit)
533561
}
@@ -541,6 +569,7 @@ mod tests {
541569
Phase,
542570
};
543571
use frame_support::{assert_noop, assert_ok, assert_storage_noop};
572+
use sp_runtime::Percent;
544573

545574
#[test]
546575
fn cannot_submit_too_early() {
@@ -779,6 +808,56 @@ mod tests {
779808
})
780809
}
781810

811+
#[test]
812+
fn geometric_deposit_queue_size_works() {
813+
let constant = vec![1000; 10];
814+
// geometric progression with 10% increase in each iteration for 10 terms.
815+
let progression_10 = vec![1000, 1100, 1210, 1331, 1464, 1610, 1771, 1948, 2143, 2357];
816+
let progression_40 = vec![1000, 1400, 1960, 2744, 3841, 5378, 7529, 10541, 14757, 20661];
817+
818+
let check_progressive_base_fee = |expected: &Vec<u64>| {
819+
for s in 0..SignedMaxSubmissions::get() {
820+
let account = 99 + s as u64;
821+
Balances::make_free_balance_be(&account, 10000000);
822+
let mut solution = raw_solution();
823+
solution.score.minimal_stake -= s as u128;
824+
825+
assert_ok!(MultiPhase::submit(RuntimeOrigin::signed(account), Box::new(solution)));
826+
assert_eq!(balances(&account).1, expected[s as usize])
827+
}
828+
};
829+
830+
ExtBuilder::default()
831+
.signed_max_submission(10)
832+
.signed_base_deposit(1000, true, Percent::from_percent(0))
833+
.build_and_execute(|| {
834+
roll_to_signed();
835+
assert!(MultiPhase::current_phase().is_signed());
836+
837+
check_progressive_base_fee(&constant);
838+
});
839+
840+
ExtBuilder::default()
841+
.signed_max_submission(10)
842+
.signed_base_deposit(1000, true, Percent::from_percent(10))
843+
.build_and_execute(|| {
844+
roll_to_signed();
845+
assert!(MultiPhase::current_phase().is_signed());
846+
847+
check_progressive_base_fee(&progression_10);
848+
});
849+
850+
ExtBuilder::default()
851+
.signed_max_submission(10)
852+
.signed_base_deposit(1000, true, Percent::from_percent(40))
853+
.build_and_execute(|| {
854+
roll_to_signed();
855+
assert!(MultiPhase::current_phase().is_signed());
856+
857+
check_progressive_base_fee(&progression_40);
858+
});
859+
}
860+
782861
#[test]
783862
fn call_fee_refund_is_limited_by_signed_max_refunds() {
784863
ExtBuilder::default().build_and_execute(|| {

0 commit comments

Comments
 (0)