Skip to content

Commit 954a248

Browse files
fix(torus0/stake): refund stake before clearing map (#113)
This patch fixes the de-registration code to clear the map after the stake has been refunded to the accounts. A previous test case ensure the _wrong_ behavior, which is now fixed. An agent this week deregistered and got its tokens locked because of order of operations. Luckly, because the TotalStake storage is still wrong, the imbalance represents the amount needed to be refunded without minting new tokens. Closes CHAIN-103. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Resolved an issue in staking logic to ensure proper refunding of stake during agent unregistration and runtime upgrades. - Updated migration logic to correct stake imbalances from previous versions. - **Refactor** - Improved clarity and maintainability of stake removal logic. - Enhanced parameter naming for better readability. - Modified operation order in agent unregistration for consistency. - **Tests** - Revised and renamed tests to better reflect updated agent unregistration and staking behaviors. - **Chores** - Updated runtime and storage version numbers to reflect the latest changes. - Introduced workspace-wide linting configurations for consistent code quality. - Enforced stricter Clippy lint rules across the workspace. - Applied saturating arithmetic in various runtime and pallet modules to prevent overflow issues. - Improved arithmetic safety and robustness in emission and governance modules. - Refined author identification and gas limit calculations with safer arithmetic operations. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent fe22d9b commit 954a248

File tree

22 files changed

+210
-125
lines changed

22 files changed

+210
-125
lines changed

Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ resolver = "2"
1313
authors = ["Renlabs <[email protected]>"]
1414
edition = "2021"
1515

16+
[workspace.lints.clippy]
17+
all = "deny"
18+
arithmetic_side_effects = "deny"
19+
indexing_slicing = "deny"
20+
panicking_unwrap = "deny"
21+
out_of_bounds_indexing = "deny"
22+
match_bool = "deny"
23+
infinite_loop = "deny"
24+
1625
[workspace.dependencies]
1726

1827
# Local

node/src/service.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ type InherentDataProviders = (
152152
fp_dynamic_fee::InherentDataProvider,
153153
);
154154

155+
#[allow(clippy::type_complexity)]
155156
fn aura_data_provider(
156157
slot_duration: sp_consensus_aura::SlotDuration,
157158
eth_config: &EthConfiguration,

pallets/emission0/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ license = "MIT-0"
66
authors.workspace = true
77
edition.workspace = true
88

9+
[lints]
10+
workspace = true
11+
912
[features]
1013
default = ["std"]
1114
std = [

pallets/emission0/src/distribute.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,11 @@ pub fn get_total_emission_per_block<T: Config>() -> BalanceOf<T> {
7272
}
7373

7474
let interval = T::HalvingInterval::get();
75-
let halving_count = total_issuance.saturating_div(interval.get());
75+
let halving_count = total_issuance.checked_div(interval.get()).unwrap_or(0);
7676
let emission = T::BlockEmission::get() >> halving_count;
7777

78-
let not_recycled = Percent::one() - crate::EmissionRecyclingPercentage::<T>::get();
78+
let not_recycled =
79+
Percent::one().saturating_sub(crate::EmissionRecyclingPercentage::<T>::get());
7980
not_recycled.mul_floor(emission)
8081
}
8182

@@ -180,7 +181,8 @@ impl<T: Config> ConsensusMemberInput<T> {
180181
member: ConsensusMember<T>,
181182
min_validator_stake: u128,
182183
) -> ConsensusMemberInput<T> {
183-
let weight_factor = Percent::one() - <T::Torus>::weight_penalty_factor(&agent_id);
184+
let weight_factor =
185+
Percent::one().saturating_sub(<T::Torus>::weight_penalty_factor(&agent_id));
184186

185187
let mut total_stake = 0;
186188
let stakes = <T::Torus>::staked_by(&agent_id)
@@ -462,17 +464,17 @@ fn compute_emissions<'a, T: Config>(
462464
let dividends_to_be_emitted;
463465

464466
if let Some(incentives_ratio) = incentives_ratio.checked_sub(50) {
465-
let incentives_percentage = Percent::from_parts(incentives_ratio * 2);
467+
let incentives_percentage = Percent::from_parts(incentives_ratio.saturating_mul(2));
466468
let incentives = incentives_percentage.mul_floor(to_be_emitted);
467469
incentives_to_be_emitted = to_be_emitted.saturating_add(incentives);
468470
dividends_to_be_emitted = to_be_emitted.saturating_sub(incentives);
469-
} else if let Some(dividends_ratio) = 50u8.checked_sub(incentives_ratio) {
470-
let dividends_percentage = Percent::from_parts(dividends_ratio * 2);
471+
} else {
472+
let dividends_ratio = 50u8.saturating_sub(incentives_ratio);
473+
474+
let dividends_percentage = Percent::from_parts(dividends_ratio.saturating_mul(2));
471475
let dividends = dividends_percentage.mul_floor(to_be_emitted);
472476
dividends_to_be_emitted = to_be_emitted.saturating_add(dividends);
473477
incentives_to_be_emitted = to_be_emitted.saturating_sub(dividends);
474-
} else {
475-
unreachable!()
476478
}
477479

478480
let incentives =

pallets/emission0/tests/distribution.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(clippy::indexing_slicing)]
2+
13
use std::array::from_fn;
24

35
use pallet_emission0::{

pallets/governance/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ license = "MIT-0"
66
authors.workspace = true
77
edition.workspace = true
88

9+
[lints]
10+
workspace = true
11+
912
[features]
1013
default = ["std"]
1114
std = [

pallets/governance/src/application.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ pub fn submit_application<T: crate::Config>(
9191
.ok()
9292
.expect("blockchain will not exceed 2^64 blocks; QED.");
9393

94-
let expires_at = current_block + config.agent_application_expiration;
94+
let expires_at = current_block.saturating_add(config.agent_application_expiration);
9595

9696
let next_id = AgentApplications::<T>::iter()
9797
.count()

pallets/governance/src/proposal.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl<T: crate::Config> Proposal<T> {
4646

4747
pub fn execution_block(&self) -> Block {
4848
match self.data {
49-
ProposalData::Emission { .. } => self.creation_block + 21_600,
49+
ProposalData::Emission { .. } => self.creation_block.saturating_add(21_600),
5050
_ => self.expiration_block,
5151
}
5252
}
@@ -402,7 +402,7 @@ fn add_proposal<T: crate::Config>(
402402
let proposal = Proposal::<T> {
403403
id: proposal_id,
404404
proposer,
405-
expiration_block: current_block + config.proposal_expiration,
405+
expiration_block: current_block.saturating_add(config.proposal_expiration),
406406
data,
407407
status: ProposalStatus::Open {
408408
votes_for: BoundedBTreeSet::new(),

pallets/governance/tests/voting.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(clippy::arithmetic_side_effects)]
2+
13
use pallet_emission0::PendingEmission;
24
use pallet_governance::{
35
config::GovernanceConfiguration,

pallets/torus0/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ license = "MIT-0"
66
authors.workspace = true
77
edition.workspace = true
88

9+
[lints]
10+
workspace = true
11+
912
[features]
1013
default = ["std"]
1114
std = [

0 commit comments

Comments
 (0)