# Unbound account in instruction validation

Does the handler bind every caller-supplied account to its owner or canonical key before acting?

_Area: Smart contract access control and control flow. Seen in 2 disclosed reports; latest 2024-05-29. Updated 2026-10-23._

## How it works
A handler trusts an account the caller supplies (a position, record, or token source) without proving it belongs to the current context. The check that exists validates some keys but not the one that ties the instruction to the state being changed, so a caller substitutes a different valid account and the action lands on the wrong record. The broken assumption: "if the instruction is authorized, the accounts in it are the right ones."

## Where it shows up
- Cross-instruction or CPI/introspection checks that compare trader, pool, or owner but skip the position/state account [E1](https://bugbountylibrary.com/r/c4%3A2024-04-lavarage%3AH-01.md)
- Wrapper or token contracts that delegate to a marketplace and never debit the owner before the external call [E2](https://bugbountylibrary.com/r/sherlock%3A2022-10-illuminate%3AH-7.md)
- `seeds()` helpers used for `invoke_signed` that omit the stored canonical bump [E3](https://bugbountylibrary.com/r/sherlock%3A2024-08-woofi-solana-deployment%3AH-1.md)
- Verifiers that infer intent from one top-level field (e.g. `tx.To`) that an intermediary can change [E4](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-21.md)
- Any `o == msg.sender` style guard that is a no-op because the contract is always the caller [E2](https://bugbountylibrary.com/r/sherlock%3A2022-10-illuminate%3AH-7.md)

## How to review
For each caller-supplied account, find the line that binds it to the owner or canonical key, and confirm it is checked, not assumed. The invariant: every account whose state is read or mutated must be proven equal to the canonical account for this instruction (owner match, PDA derivation with bump, or key equality against the referenced instruction). For delegated sells, confirm shares move owner→contract before the external call [E2](https://bugbountylibrary.com/r/sherlock%3A2022-10-illuminate%3AH-7.md). For PDA signing, confirm the seed array includes the bump [E3](https://bugbountylibrary.com/r/sherlock%3A2024-08-woofi-solana-deployment%3AH-1.md). For inbound verification, confirm the logical action cannot be rerouted through a wrapper that changes the checked field [E4](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-21.md).

## Variants seen
- Missing position-account binding in a repay/close check [E1](https://bugbountylibrary.com/r/c4%3A2024-04-lavarage%3AH-01.md)
- Owner never debited; contract's own balance sold [E2](https://bugbountylibrary.com/r/sherlock%3A2022-10-illuminate%3AH-7.md)
- PDA seeds missing bump, breaking CPI signing [E3](https://bugbountylibrary.com/r/sherlock%3A2024-08-woofi-solana-deployment%3AH-1.md)
- Intent inferred from `tx.To`, defeated by intermediary contracts [E4](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-21.md)

## Impact and severity
Led to collateral withdrawn without repaying a loan [E1](https://bugbountylibrary.com/r/c4%3A2024-04-lavarage%3AH-01.md), anyone draining held PTs [E2](https://bugbountylibrary.com/r/sherlock%3A2022-10-illuminate%3AH-7.md), locked tokens from failed CPI signing [E3](https://bugbountylibrary.com/r/sherlock%3A2024-08-woofi-solana-deployment%3AH-1.md), and dropped valid deposits [E4](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-21.md). Severity rises when the unbound account controls funds or when the failure is silent (locked funds, missed deposits) rather than reverting.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2024-04-lavarage%3AH-01.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2022-10-illuminate%3AH-7.md
- E3: https://bugbountylibrary.com/r/sherlock%3A2024-08-woofi-solana-deployment%3AH-1.md
- E4: https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-21.md
