Root Cause
Rain's crypto card infrastructure uses a versioned smart contract to manage card-collateral accounts. The attacker identified that an older, unpatched contract version remained deployed and active. The legacy contract exposed an administrative function that lacked an access-control modifier — when called with correct parameters, it transferred ownership of individual collateral sub-accounts to the caller.
// Illustrative vulnerable pattern (reconstructed from incident description)
// Legacy contract: missing access-control on admin-transfer function
function transferCardAccount(address newAdmin) external {
// Missing: require(msg.sender == owner, "Unauthorized");
cardAdmin[tx.origin] = newAdmin; // unguarded privileged setter
}
The attacker exploited this to iteratively seize ownership of collateral accounts belonging to users of both Avici and Tria neobanks, then drained each account's balance before Rain could respond.
Attack Steps
| Step | Action |
|---|---|
| 1 | Attacker discovers unpatched legacy Rain card contract still in production use |
| 2 | Calls unguarded admin-transfer function on targeted card-collateral accounts |
| 3 | Gains administrative control over individual accounts without owning them |
| 4 | Iteratively withdraws full balances from seized accounts |
| 5 | Bridges stolen Solana-native funds to Ethereum |
| 6 | Routes proceeds through Tornado Cash to obscure the trail |
Impact
- Avici neobank: ~$500,800 drained across 1,685 user accounts
- Tria neobank: ~$430,000+ drained across 636 user accounts
- Total loss: ~$1.1M
- AVICI token: Fell 49% to a record low of $0.217
- Both neobanks pledged full user compensation; Rain upgraded all legacy contract instances post-incident
Lessons for Auditors
- Version hygiene is a first-class security property. When a new contract version is deployed, old versions must be deprecated and migrated — leaving both live creates a persistent attack surface that audits of the current version miss entirely.
- Admin and ownership-transfer functions require explicit access controls. Any function that mutates privileged roles must verify the current authorised caller, not merely the transaction sender.
- Audit all deployed versions, not just the latest. Enumerate every live deployment address and verify each against the current security baseline as part of a pre-audit scoping exercise.
- Monitor bridge outflows immediately post-exploit. The Solana → Ethereum → Tornado Cash laundering path is a standard attacker playbook; anomalous bridge volume is often the earliest on-chain signal of an ongoing incident.