fix: prevent u64 underflow in validator_claim_fees and use on-chain Rent sysvar#179
fix: prevent u64 underflow in validator_claim_fees and use on-chain Rent sysvar#179amathxbt wants to merge 1 commit into
Conversation
…ent sysvar Two related bugs in process_validator_claim_fees: 1. Rent::default() returns hardcoded default values that may differ from the actual on-chain rent schedule. Replaced with Rent::get()? which reads the current on-chain Sysvar. 2. Both occurrences of validator_fees_vault.lamports() - min_rent were plain u64 subtractions. If the vault somehow holds fewer lamports than min_rent (e.g. due to a prior accounting bug or a griefing vector that drains rent below the exemption threshold), the subtraction wraps around to a very large u64 in release builds, bypassing the insufficient-funds guard and potentially allowing an attacker to drain an arbitrary amount. Fix: use checked_sub(...).ok_or(ProgramError::InsufficientFunds) so the instruction returns an error instead of underflowing.
📝 WalkthroughWalkthroughThe ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 0/1 reviews remaining, refill in 60 minutes.Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/processor/validator_claim_fees.rs`:
- Around line 53-56: The protocol_claim_fees.rs code still uses
Rent::default().minimum_balance(8) and performs an unchecked subtraction;
replace that pattern by retrieving the on-chain rent with Rent::get()? and
computing minimum_balance using the actual account data length (e.g.,
fees_vault.data_len()), assign to a min_rent variable, and use a checked
subtraction (checked_sub) when subtracting min_rent from balances to avoid
underflow—locate the logic around fees_vault and the current
minimum_balance/subtraction and update it to mirror the validator_claim_fees.rs
approach.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 99f817bb-4215-4bd0-9aa7-d99d62da5a91
📒 Files selected for processing (1)
src/processor/validator_claim_fees.rs
| // Use the on-chain Rent sysvar (not `Rent::default()`) and the actual | ||
| // account data length so the minimum-balance threshold is always accurate. | ||
| let min_rent = | ||
| Rent::get()?.minimum_balance(validator_fees_vault.data_len()); |
There was a problem hiding this comment.
protocol_claim_fees.rs retains the same unfixed pattern.
src/processor/protocol_claim_fees.rs:53-60 still uses Rent::default().minimum_balance(8) with unchecked subtraction — the exact vulnerability this PR was raised to fix. Consider applying the same Rent::get()?.minimum_balance(fees_vault.data_len()) + checked_sub treatment there before the next release.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/processor/validator_claim_fees.rs` around lines 53 - 56, The
protocol_claim_fees.rs code still uses Rent::default().minimum_balance(8) and
performs an unchecked subtraction; replace that pattern by retrieving the
on-chain rent with Rent::get()? and computing minimum_balance using the actual
account data length (e.g., fees_vault.data_len()), assign to a min_rent
variable, and use a checked subtraction (checked_sub) when subtracting min_rent
from balances to avoid underflow—locate the logic around fees_vault and the
current minimum_balance/subtraction and update it to mirror the
validator_claim_fees.rs approach.
Summary
This PR fixes two related bugs in
process_validator_claim_fees(src/processor/validator_claim_fees.rs).Bug 1 —
Rent::default()uses hardcoded values, not the on-chain scheduleRent::default()constructs aRentstruct with compile-time defaults that may drift from the actual on-chain rent configuration. The correct approach is to read the Sysvar from the runtime viaRent::get()?. Additionally the hardcoded data-length argument8is replaced with the actualvalidator_fees_vault.data_len()so the minimum-balance threshold is always correct regardless of account size.Bug 2 — Unchecked subtraction can underflow and bypass the insufficient-funds guard
Both subtractions are plain
u64arithmetic. If the vault ever holds fewer lamports thanmin_rent(possible after a prior accounting error or if a griefing vector reduces the balance below rent-exemption), the subtraction wraps around in release builds to a very largeu64. This makesamounta huge default value and causes the guard condition to evaluate incorrectly, potentially allowing an unauthorised withdrawal of an arbitrary amount.Fix: Compute the available balance once with
checked_sub(...).ok_or(ProgramError::InsufficientFunds)?and reuse the result, eliminating both raw subtractions.Fix
Impact
delegation-program / src/processor/validator_claim_fees.rsSummary by CodeRabbit