# Unblocked deposit breaks invariant

Check every module/account that accepts deposits against the invariant it must preserve

_Area: Smart contract access control and control flow. Seen in 2 disclosed reports; latest 2026-03-07. Updated 2026-10-24._

## How it works
A module or account is meant to receive funds only through expected state-machine paths, so its balance and accounting stay consistent with a later invariant. If nothing blocks arbitrary deposits, any user can push funds in and break that invariant. The assumption that breaks: "only the protocol can move value into this account." When the account is reachable by ordinary transfers, the invariant no longer holds and downstream logic that trusts it fails, sometimes catastrophically.

## Where it shows up
- Module accounts not listed in a blocked-address map (e.g. Cosmos x/bank blocked addresses) [E1](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-33.md)
- Accounts whose balance feeds an invariant but accept direct transfers
- Address sentinels (native ETH as 0x0) cast to a contract interface [E3](https://bugbountylibrary.com/r/cantina%3Avii_finance_jan2026%3A3.1.5.md)
- try/catch around external calls that assumes reverts come from inside the callee [E3](https://bugbountylibrary.com/r/cantina%3Avii_finance_jan2026%3A3.1.5.md)
- Emulation layers where opcode edge cases (empty accounts, precompiles) diverge from spec [E2](https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-19.md)

## How to review
Enumerate every module/account that holds value or is read by invariant logic. For each, confirm the exact property: either the account is blocked from arbitrary deposits, or the invariant is computed in a way that tolerates unsolicited balance. Check the blocked-address map covers all module accounts [E1](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-33.md). For calls, verify the target is a real contract before casting, and remember try/catch does not catch reverts at the call site (non-contract address) [E3](https://bugbountylibrary.com/r/cantina%3Avii_finance_jan2026%3A3.1.5.md). For opcode emulation, diff each implementation against its EIP, especially emptiness checks that must consider code, nonce and balance [E2](https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-19.md).

## Variants seen
- Module account missing from blocked-address map, halting the chain [E1](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-33.md)
- Opcode emulation diverging from EIP-1052 on empty accounts and precompiles [E2](https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-19.md)
- Native-currency sentinel cast to interface, reverting and blocking withdrawals [E3](https://bugbountylibrary.com/r/cantina%3Avii_finance_jan2026%3A3.1.5.md)

## Why fixes fail
Blocking one account does not generalize; the same gap recurs for other module accounts unless the map is audited exhaustively [E1](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-33.md). try/catch gives false safety because it only catches callee reverts, not call-site reverts [E3](https://bugbountylibrary.com/r/cantina%3Avii_finance_jan2026%3A3.1.5.md).

## Impact and severity
Ranged from full chain halt [E1](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-33.md) to blocked LP withdrawals (DoS) [E3](https://bugbountylibrary.com/r/cantina%3Avii_finance_jan2026%3A3.1.5.md) and EVM-equivalence divergence [E2](https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-19.md). Severity rises when the broken invariant gates core functionality or funds; worse when the deposit path is permissionless and the invariant is checked late.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-33.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-10-zksync%3AM-19.md
- E3: https://bugbountylibrary.com/r/cantina%3Avii_finance_jan2026%3A3.1.5.md
