Skip to main content
Sigvex

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.

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

  1. Compute maximum withdrawal: let max_withdraw = account.lamports() - rent.minimum_balance(data_len); and cap the withdrawal amount.
  2. an account-validation framework constraint: add a constraint attribute that validates rent preservation inline.
  3. Withdrawal helper: centralize the rent check in a reusable function to ensure consistency.

Common Mistakes

  • Using unchecked subtraction: account.lamports() - amount can underflow. Always use checked_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.

References