SPL Token Delegation Chain Depth Remediation
How to fix excessive delegation chain depth in Solana programs.
SPL Token Delegation Chain Depth Remediation
Overview
Related Detector: SPL Token Delegation Chain Depth
Excessive delegation chain depth creates compounding security risks where compromise at any hop affects all downstream delegates. The fix involves enforcing maximum depth limits and preferring direct delegation over chains.
Recommended Fix
Before (Vulnerable)
// No depth limit -- allows unbounded delegation chains
pub fn delegate(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
let ix = spl_token::instruction::approve(
&spl_token::id(), accounts[0].key, accounts[1].key,
accounts[2].key, &[], amount,
)?;
invoke(&ix, accounts)?;
Ok(())
}
After (Fixed)
const MAX_DELEGATION_DEPTH: u8 = 3;
pub fn delegate(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
// Track and enforce delegation depth
let state = load_delegation_state(accounts[0])?;
if state.depth >= MAX_DELEGATION_DEPTH {
msg!("Delegation chain depth {} exceeds maximum {}", state.depth, MAX_DELEGATION_DEPTH);
return Err(ProgramError::Custom(ErrorCode::ExcessiveDelegationDepth as u32));
}
let ix = spl_token::instruction::approve(
&spl_token::id(), accounts[0].key, accounts[1].key,
accounts[2].key, &[], amount,
)?;
invoke(&ix, accounts)?;
// Update depth tracking
save_delegation_state(accounts[0], state.depth + 1)?;
Ok(())
}
Alternative Mitigations
1. Direct delegation only
Redesign the protocol to only allow single-hop delegation, eliminating chains entirely.
2. Access control lists
Replace delegation chains with an explicit ACL stored in program state, where each authorized account is listed directly.
3. PDA-based authority
Use PDAs as intermediary authorities so that only your program can exercise delegation, eliminating untrusted intermediate delegates.
Common Mistakes
Mistake 1: Not tracking delegation depth
// WRONG: no depth tracking -- chains can grow indefinitely
Mistake 2: Allowing re-delegation of delegated authority
// RISKY: a delegate re-delegating creates implicit chains
// Consider preventing delegates from further delegating