Rent Exempt Epoch Transition
Detects cached rent-exempt minimum balances that become stale across epoch transitions.
Rent Exempt Epoch Transition
Overview
Remediation Guide: How to Fix Rent Exempt Epoch Transition
The rent-exempt epoch transition detector identifies programs that cache the rent-exempt minimum balance in account data instead of querying the Rent sysvar dynamically. If Solana changes rent parameters across epochs, cached values become stale and balance checks using them may incorrectly consider an account rent-exempt when it is not, leading to garbage collection of important state accounts.
Sigvex tracks variables derived from Rent sysvar reads and flags StoreAccountData operations that write rent-derived values to account data (caching pattern).
Why This Is an Issue
- Stale balance checks: a cached rent-exempt minimum may be lower than the actual requirement after an epoch transition, causing accounts to fail rent checks silently.
- Cross-transaction staleness: the cached value is written in one transaction and read in a future one, potentially across multiple epochs.
- Incorrect withdrawal limits: programs that compute maximum withdrawal amounts from cached rent values may allow over-withdrawal.
CWE mapping: CWE-672 (Operation on a Resource after Expiration or Release).
How to Resolve
Native Solana
// CORRECT: Always query Rent dynamically
let rent = Rent::get()?;
let min_balance = rent.minimum_balance(account.data_len());
require!(account.lamports() >= min_balance, NotRentExempt);
Anchor
// Anchor queries Rent internally for init/realloc constraints
#[account(init, payer = user, space = 8 + 64)]
pub state: Account<'info, MyState>,
Examples
Vulnerable
// Caching rent minimum in account data
let rent = Rent::get()?;
let min = rent.minimum_balance(account.data_len());
let mut data = account.data.borrow_mut();
data[32..40].copy_from_slice(&min.to_le_bytes()); // Cached — becomes stale!
Fixed
// Always query fresh
let rent = Rent::get()?;
let min = rent.minimum_balance(account.data_len());
require!(account.lamports() >= min, NotRentExempt);
JSON Finding
{
"detector": "rent-exempt-epoch-transition",
"severity": "Medium",
"confidence": 0.75,
"title": "Rent-Exempt Minimum Cached in Account Data",
"description": "Program stores rent-exempt minimum balance into account data, creating a stale cached value.",
"cwe": [672]
}
Detection Methodology
The detector collects variables derived from Rent sysvar reads (syscalls containing “rent”, “minimum_balance”, or “is_exempt”), then checks for StoreAccountData operations that reference these variables. It also flags functions that use rent-derived values in conditional branches without caching, as a lower-severity informational finding.
Limitations
- The detector cannot track rent values passed between functions or stored in global state.
- Programs that cache rent for compute-budget optimization but include refresh mechanisms may still be flagged.
- Anchor programs receive reduced confidence since Anchor queries rent dynamically.
Related Detectors
- Rent Epoch Validation - detects improper rent epoch handling.
- Missing Rent Check - detects transfers without rent checks.