Skip to content

Commit ba0f8de

Browse files
authored
[pallet-broker] Fix claim revenue behaviour for zero timeslices (paritytech#3997)
This PR adds a check that `max_timeslices > 0` and errors if not. It also adds a test for this behaviour and cleans up some misleading docs.
1 parent d3eba36 commit ba0f8de

4 files changed

Lines changed: 29 additions & 6 deletions

File tree

prdoc/pr_3997.prdoc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
2+
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
3+
4+
title: "[pallet-broker] Fix claim revenue behaviour for zero timeslices"
5+
6+
doc:
7+
- audience: Runtime Dev
8+
description: |
9+
Add a check in the `claim_revenue` broker call to ensure that max_timeslices > 0 and errors if
10+
not. This mitigates an issue where an attacker could call claim_revenue for an existing region
11+
that is owed a revenue, with max_timeslices set to 0 for free indefinitely, which would
12+
represent an unbounded spam attack.
13+
14+
crates:
15+
- name: pallet-broker
16+
bump: patch

substrate/frame/broker/src/dispatchable_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ impl<T: Config> Pallet<T> {
329329
mut region: RegionId,
330330
max_timeslices: Timeslice,
331331
) -> DispatchResult {
332+
ensure!(max_timeslices > 0, Error::<T>::NoClaimTimeslices);
332333
let mut contribution =
333334
InstaPoolContribution::<T>::take(region).ok_or(Error::<T>::UnknownContribution)?;
334335
let contributed_parts = region.mask.count_ones();

substrate/frame/broker/src/lib.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,8 @@ pub mod pallet {
474474
AlreadyExpired,
475475
/// The configuration could not be applied because it is invalid.
476476
InvalidConfig,
477+
/// The revenue must be claimed for 1 or more timeslices.
478+
NoClaimTimeslices,
477479
}
478480

479481
#[pallet::hooks]
@@ -680,13 +682,12 @@ pub mod pallet {
680682

681683
/// Claim the revenue owed from inclusion in the Instantaneous Coretime Pool.
682684
///
683-
/// - `origin`: Must be a Signed origin of the account which owns the Region `region_id`.
685+
/// - `origin`: Must be a Signed origin.
684686
/// - `region_id`: The Region which was assigned to the Pool.
685-
/// - `max_timeslices`: The maximum number of timeslices which should be processed. This may
686-
/// effect the weight of the call but should be ideally made equivalent to the length of
687-
/// the Region `region_id`. If it is less than this, then further dispatches will be
688-
/// required with the `region_id` which makes up any remainders of the region to be
689-
/// collected.
687+
/// - `max_timeslices`: The maximum number of timeslices which should be processed. This
688+
/// must be greater than 0. This may affect the weight of the call but should be ideally
689+
/// made equivalent to the length of the Region `region_id`. If less, further dispatches
690+
/// will be required with the same `region_id` to claim revenue for the remainder.
690691
#[pallet::call_index(12)]
691692
#[pallet::weight(T::WeightInfo::claim_revenue(*max_timeslices))]
692693
pub fn claim_revenue(

substrate/frame/broker/src/tests.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ fn instapool_payouts_work() {
372372
advance_to(11);
373373
assert_eq!(pot(), 14);
374374
assert_eq!(revenue(), 106);
375+
376+
// Cannot claim for 0 timeslices.
377+
assert_noop!(Broker::do_claim_revenue(region, 0), Error::<Test>::NoClaimTimeslices);
378+
379+
// Revenue can be claimed.
375380
assert_ok!(Broker::do_claim_revenue(region, 100));
376381
assert_eq!(pot(), 10);
377382
assert_eq!(balance(2), 4);

0 commit comments

Comments
 (0)