Rent Withdrawal Balance Remediation
How to fix partial lamport withdrawals without rent-exemption checks.
Rent Withdrawal Balance Remediation
Overview
Detector Reference: Rent Withdrawal Balance
This guide explains how to ensure partial lamport withdrawals preserve rent exemption.
Recommended Fix
Before every partial withdrawal, verify the remaining balance exceeds the rent-exempt minimum:
let rent = Rent::get()?;
let min_balance = rent.minimum_balance(account.data_len());
let remaining = account.lamports()
.checked_sub(withdrawal_amount)
.ok_or(ProgramError::InsufficientFunds)?;
require!(remaining >= min_balance, ErrorCode::WouldBreakRentExemption);
**account.try_borrow_mut_lamports()? -= withdrawal_amount;
**destination.try_borrow_mut_lamports()? += withdrawal_amount;
Alternative Mitigations
- Compute maximum withdrawal:
let max_withdraw = account.lamports() - rent.minimum_balance(data_len);and cap the withdrawal amount. - Anchor constraint: add a
constraintattribute that validates rent preservation inline. - Withdrawal helper: centralize the rent check in a reusable function to ensure consistency.
Common Mistakes
- Using unchecked subtraction:
account.lamports() - amountcan underflow. Always usechecked_sub. - Checking the wrong account: ensure the balance check is on the source account, not the destination.
- Not accounting for data length changes: if the account was recently reallocated, use the current data length for rent calculation.