Repository navigation
get_economic_exposure totals use saturating_add with no signal: unlike increment_stats, exposure overflow caps silently #481
Copy link
Copy link
Closed
Labels
GrantFox OSSIssue tracked in GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardIssue may be eligible for a GrantFox rewardStellar WaveIssues in the Stellar wave programIssues in the Stellar wave programThird CampaignCampaign: Third CampaignCampaign: Third Campaignarea/apiImported campaign issue labelImported campaign issue labelpriority/mediumImported campaign issue labelImported campaign issue label
Description
Problem
get_economic_exposure (src/lib.rs) aggregates totals with silent saturation:
total_max_reward = total_max_reward.saturating_add(max_reward);
total_penalty_per_minute = total_penalty_per_minute.saturating_add(penalty_rate);The running stats path (increment_stats) went to lengths to surface saturation — checked_add + stats_sat events (SC-W5-047) — but the exposure view caps at i128::MAX with no signal.
Consequences:
- The exposure view can under-report with no indication: with four canonical severities plus custom entries (if the companion issue lands), sums near
i128::MAXclamp silently; a dashboard readingtotal_max_reward == i128::MAXcannot tell whether that is a real configured total or a saturation artifact. - The two aggregation paths set different precedents:
increment_statstreats saturation as reportable (event, capped value),get_economic_exposuretreats it as invisible — a consumer that learned the stats convention will not expect the view to lie silently. - The view is read-only and stateless: it cannot emit events, so the fix must either avoid saturation (e.g. return an error) or expose the saturation state in the response.
Root cause
The view was written with saturating_add as a cheap overflow guard, predating the stats_sat convention; the two paths were never reconciled.
Why this is architecturally hard
- The response types (
EconomicExposure,SeverityExposure) are#[contracttype]and stability-guarded; adding asaturated: boolfield is additive but requires the guardrail update (companion issue). - Returning an error on overflow changes the endpoint's contract (read-only views are expected to succeed); the design decision is signal-in-response vs. error.
- In practice the configured bounds (reward_base ≤ 100,000, four severities) make overflow unreachable today — so the issue is about correctness-by-construction: either document the unreachability or make the math checked so a future bound change cannot silently corrupt totals.
Acceptance criteria
- Exposure totals cannot silently cap (checked math with a defined signal, or documented unreachability with an assertion).
- The behavior is consistent with the
stats_satconvention or explicitly divergent with rationale. - Tests cover the extreme-configuration case.
Out of scope
The custom-severity omission in the view (companion issue in batch 06) and the reward-tier boundary tests.
Getting started
just testGood first files to read: apexchainx_calculator/src/lib.rs (get_economic_exposure, increment_stats).
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
GrantFox OSSIssue tracked in GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardIssue may be eligible for a GrantFox rewardStellar WaveIssues in the Stellar wave programIssues in the Stellar wave programThird CampaignCampaign: Third CampaignCampaign: Third Campaignarea/apiImported campaign issue labelImported campaign issue labelpriority/mediumImported campaign issue labelImported campaign issue label
Activity
safal207 commentedon Aug 27, 2026
One API-design question before I start: would you prefer a new typed "ExposureOverflow" error, preserving the current "EconomicExposure" response shape, or an additive "saturated: bool" field, keeping the view non-failing?
I checked the current "main": "get_economic_exposure" silently clamps at two independent layers—per-severity arithmetic via "unwrap_or(i128::MAX)", then aggregate totals via "saturating_add". A regression test should cover both paths; otherwise a per-severity overflow may already look like a valid maximum before aggregation.
I can take this on with:
Relevant completed work: merged "StreamPay #161" (Streampay-Org/StreamPay-Contracts#161) and "CommitLabs #556" (Commitlabs-Org/Commitlabs-Contracts#556), both focused on deterministic invariants and failure boundaries.
If this approach matches the intended compatibility policy, please assign me. I can open a focused PR within 24 hours after the design choice is confirmed and will wait for assignment before changing production code.
abdulquadri123 commentedon Aug 30, 2026
@abdulquadri123 has applied to work on this issue as part of the Stellar Wave Program's 8th wave.
ℹ️ Repo Maintainers: To accept this application, review their application or assign @abdulquadri123 to this issue.
AGWAM001 commentedon Aug 30, 2026
@AGWAM001 has applied to work on this issue as part of the Stellar Wave Program's 8th wave.
ℹ️ Repo Maintainers: To accept this application, review their application or assign @AGWAM001 to this issue.
Abulbayty commentedon Aug 30, 2026
@Abulbayty has applied to work on this issue as part of the Stellar Wave Program's 8th wave.
ℹ️ Repo Maintainers: To accept this application, review their application or assign @Abulbayty to this issue.
poaspergillus commentedon Aug 30, 2026
@poaspergillus has applied to work on this issue as part of the Stellar Wave Program's 8th wave.
ℹ️ Repo Maintainers: To accept this application, review their application or assign @poaspergillus to this issue.
DevMuhdishaq commentedon Aug 30, 2026
@DevMuhdishaq has applied to work on this issue as part of the Stellar Wave Program's 8th wave.
ℹ️ Repo Maintainers: To accept this application, review their application or assign @DevMuhdishaq to this issue.
chainsmt commentedon Aug 30, 2026
@chainsmt has applied to work on this issue as part of the Stellar Wave Program's 8th wave.
ℹ️ Repo Maintainers: To accept this application, review their application or assign @chainsmt to this issue.
drips-wave commentedon Aug 30, 2026
Congratulations, @DevMuhdishaq! 🎉 Your application was accepted by the repo's maintainers, and the issue is due on August 31, 2026.
🧑💻 @DevMuhdishaq: Please resolve the issue such that the repo's maintainers have enough time to review your contribution before the due date. You'll earn Points for completing the issue on-time, which will make you eligible for a share of the Stellar Wave Program's reward pool.
Warning
When opening a PR, please link it to this issue to ensure it gets tracked accurately. Points are awarded when this issue is marked as completed by the maintainer.
🤠 Repo maintainers: Please keep an eye on the contributor's progress and review their work before the due date. You can manage this issue, including adjusting its complexity and points, here.
🌊 Happy Wave 🌊
grantfox-oss commentedon Aug 31, 2026
🎉 This issue has been marked as completed on GrantFox!
@DevMuhdishaq's PR #548 was approved and merged by @usmanimamu17-create.
🏆 @DevMuhdishaq: You earned 40 FoxPoints for this contribution! Your current tier: Builder (1,225 total points). Track your full progress on GrantFox.
👏 Great work, @DevMuhdishaq! Keep contributing to ApexChainx.
drips-wave commentedon Aug 31, 2026
This issue has been completed by @DevMuhdishaq as part of the Stellar Wave Program's 8th Wave 🥳
😎 @DevMuhdishaq: You earned 200 Points for completing this issue! After the current Wave ends, you'll be eligible for a percentage of the Wave's reward pool based on the percentage of total points you've earned. Learn more here. You can also Leave a review to share your experience working on this issue.
🧑💻 Repo maintainers: How'd the contributor do? Leave a review to share your experience working with them.