Rain's $1.1M Card Contract Exploit: How an Outdated Solana Program Drained 2,321 Neobank Users Through a Broken Authorization Check
An attacker exploited a broken multi-signature authorization check in an outdated version of Rain's Solana card contract, granting itself withdrawal rights over user card-collateral accounts and draining roughly $1.1 million across multiple stablecoin-card programs. Avici reported $500,859 lost from 1,685 users and Tria $431,945 from 636 users. Users' self-custodial wallets and private keys were not compromised — only balances pre-committed to card funding inside Rain's shared contract. Avici's AVICI token fell 49% and the company pledged to refund affected card balances.
This article is published for educational and informational purposes only. It does not constitute legal, financial, or investment advice. Nothing in this article should be relied upon as the sole basis for any decision relating to the security, investment value, or legal standing of any protocol or digital asset.
Information published on any code vulnerabilities must not be used to attack, test, or probe any protocol or system without explicit authorisation from its owner. Use of this content is subject to our Terms of Service and Privacy Policy.
What happened
On August 28, 2026, an attacker exploited a vulnerability in an outdated version of Rain's Solana card smart contract and drained approximately $1.1 million from card-collateral accounts across multiple stablecoin-card programs built on Rain's infrastructure. The attack did not touch users' self-custodial wallets or private keys. It targeted a more specific surface: the balances users had already moved into Rain's shared card-funding contract in preparation for upcoming card spend.
Two neobanks disclosed losses directly. Avici reported approximately $500,859 drained from 1,685 affected users. Tria reported more than $431,945 from 636 affected users. Security firm Blockaid, which detected the incident through on-chain monitoring, placed the total across all Rain-supported programs at approximately $1.1 million, encompassing programs that had not yet publicly disclosed their own figures at the time of publication.
The mechanism was a flaw in access control. As described by Gadgets 360, the vulnerability in the outdated contract version allowed a single attacker-controlled signature to satisfy an authorization check that was designed to require two. Having bypassed that check, the attacker granted itself withdrawal rights over the affected collateral accounts and systematically drained them across every program running the vulnerable contract version.
The market impact fell hardest on Avici. Its native token, AVICI, fell as much as 49% following disclosure of the exploit, according to CoinDesk. Avici subsequently pledged to refund all affected card balances. Rain stated that updated contract versions were not affected and that users' self-custodial wallets remained secure.
Root cause
The root cause was an access-control flaw in an outdated version of Rain's Solana card contract - specifically, a broken multi-signature authorization check that could be satisfied by a single attacker-controlled signer. Once that check was bypassed, the contract's withdrawal permission model allowed the attacker to assign itself as an authorized withdrawer on user collateral accounts and drain them sequentially. The vulnerability was present in the deployed contract version and not in the updated version, indicating that a patch had been developed but the old deployment had not been fully migrated or retired.
Card-collateral accounts and shared infrastructure
Rain's model separates user assets into two layers. The first is the user's personal self-custodial wallet, fully under their own key control. The second is a card-collateral account within Rain's Solana card contract - a shared program that multiple neobanks deploy against - which holds the portion of a user's balance pre-committed to card spending. The card contract mediates access to this second layer. Its permission model determines who can initiate withdrawals from user collateral accounts.
Because multiple neobanks - Avici, Tria, and others - built their card programs on the same Rain contract infrastructure, a single vulnerability in the shared contract version propagated across all of them simultaneously. This is the ecosystem-level risk of shared smart contract infrastructure: a flaw in a common dependency exposes every downstream program, regardless of how carefully each neobank built its own product.
The authorization bypass
The card contract's withdrawal authorization was designed to require multiple valid signatures before allowing a withdrawal from a user's collateral account - a standard multi-signature control intended to ensure that no single party could unilaterally move user funds. The outdated contract version contained a flaw in this check that allowed a single attacker-controlled signature to satisfy the requirement. The precise mechanism of the bypass has not been fully disclosed; the available reporting describes it as the attacker being able to grant itself withdrawal rights rather than forging a missing signature.
// Intended authorization model:
// withdraw(user_collateral_account) requires:
// signer_1 = rain_authority AND
// signer_2 = program_authority
// Both required. Neither can act alone.
// Flawed contract behavior (outdated version):
// A single attacker-controlled signer can invoke a permission-grant
// instruction that writes attacker_address as an authorized withdrawer
// on a target user_collateral_account.
attacker.invoke(
instruction = grantWithdrawalRight,
target = user_collateral_account,
beneficiary = attacker_address,
// [BUG]: authorization check incorrectly satisfied by
// attacker's single signature; second required signer
// not enforced
)
// attacker_address is now a recognized withdrawer
attacker.invoke(
instruction = withdraw,
from = user_collateral_account,
to = attacker_wallet,
amount = full_balance
)
// Repeated across all affected user accounts and programs
// Total: ~2,321 users drained across Avici and Tria aloneWhy the outdated version was still in production
Rain had developed an updated contract version that did not contain the flaw. The existence of the updated version implies the vulnerability was either known and scheduled for migration, or discovered and patched after the fact but not yet fully deployed across all downstream programs. In either case, the outdated version remained live and in active use by production neobanks. The gap between the patch existing and every dependent program being migrated to it is the window in which the attack occurred.
Shared contract infrastructure compounds this migration risk. When Rain updates its card contract, every neobank built on it must separately migrate their users' collateral accounts to the new program. That process involves coordination, testing, and user communication. During the transition period, both old and new contract versions are live. If the old version contains a critical vulnerability, the migration window is a period of elevated risk - one that requires either an expedited migration or a temporary halt to card funding on the old contract.
What could have been done
- Treat contract version migration as a security-critical operation with a hard deadline. When a critical vulnerability in a shared contract is identified and patched, migrating every downstream program to the updated version should not be a best-effort background task. It should be treated with the same urgency as a live incident: a defined deadline, a migration checklist for each dependent program, and a fallback plan - such as halting new card funding on the old contract - if the deadline cannot be met. A patched contract that exists alongside a vulnerable one in production is not a remediated vulnerability; it is a partial remediation with a live attack surface still open.
- Gate permission-grant instructions with independent on-chain verification. The specific flaw was that a permission-granting instruction - one that writes new withdrawal rights onto a user collateral account - could be satisfied by a single attacker signature. Any instruction that expands permissions over user funds should require the most conservative authorization logic in the contract, not the minimum viable check. Permission escalation is the highest-risk operation a card contract performs; it should be the most heavily guarded.
- Implement withdrawal rate limits and anomaly detection at the contract level. The attacker drained thousands of accounts sequentially - 2,321 confirmed across two programs alone. Each drain was a discrete transaction. An on-chain rate limit on total withdrawals per time window, combined with a circuit breaker that pauses withdrawals if the aggregate outflow in any block or epoch exceeds a threshold, would have limited the blast radius even if the authorization bypass was not caught immediately. Blockaid's monitoring detected the incident; an equivalent check inside the contract itself would have halted execution automatically.
- Use per-user collateral accounts with isolated authorization state. If each user's card-collateral account has an entirely independent authorization state - with no shared permission-grant pathway that can be invoked from a single transaction to affect multiple accounts - then an authorization bypass affects only the account it is directly invoked against. The attacker in this case granted itself rights across many accounts by exploiting a shared contract instruction. Isolating authorization state per account raises the cost of a broad attack from one transaction to one transaction per account.
- Require time-locked permission grants for withdrawal-right changes. Any instruction that modifies withdrawal authorization on a user collateral account should have a mandatory delay before it takes effect - even if the initiating signatures are valid. A timelock of even a few minutes between a permission-grant instruction being submitted and it becoming executable would give on-chain monitoring systems a window to detect the anomaly and trigger a pause before any funds move.
- Communicate the custody model for card-funding balances clearly and separately from self-custodial wallet marketing. Users whose funds were drained had been told they were using self-custodial infrastructure. Technically, their personal wallets were self-custodial. Their card-funding balances were not; they were held inside a shared contract whose security depended on Rain's contract code, not on the user's private key. These are materially different security models, and they carry different risks. Neobanks that describe their products as self-custodial have an obligation to disclose where that description ends and where custodial or shared-contract risk begins.
Lessons for the industry
The Rain exploit is a case study in two compounding risks that are increasingly common in the neobank and crypto-card layer of DeFi: shared smart contract infrastructure as a single point of failure, and the gap between self-custodial marketing and the actual custody model for funds in transit through a payment system.
On the infrastructure risk: when multiple products are built on a shared contract program, a vulnerability in that program is a vulnerability in all of them simultaneously. The attacker did not need to identify separate flaws in Avici's product, Tria's product, or any other Rain-based program. They needed to identify one flaw in the shared Rain contract version, and every product using that version became a target in the same operation. This is the fundamental trade-off of shared contract infrastructure - it reduces development cost and promotes consistency, but it concentrates security risk. An exploitable flaw in a shared component is proportionally more dangerous than a flaw in an isolated deployment, because the number of affected users scales with the number of programs sharing the dependency.
On the migration window: the existence of an updated, non-vulnerable contract version at the time of the exploit points to a window of known but unmitigated risk. This pattern - a patch exists, deployment is incomplete, old version remains live - is among the most preventable sources of DeFi losses. A vulnerability that has been found and fixed is, in an important sense, a known risk from the moment the fix is deployed somewhere and the old version is still running elsewhere. Treating contract migration as a routine operational task, rather than a time-critical security closure, leaves that window open indefinitely.
On the self-custodial framing: the broader crypto-card and neobank sector has converged on self-custody as a differentiating claim - the idea that users hold their own keys and are not exposed to the custody risk of a centralized custodian. That claim is meaningful and accurate for the personal wallet layer. It does not automatically extend to the card infrastructure layer, where user balances pre-committed to card spend are held inside a shared smart contract program that the user cannot directly control. The Rain incident illustrates that these two layers can have fundamentally different security models within the same product. Users deserve to know where the boundary lies, and that distinction should be front and center in product documentation - not buried in a technical footnote.
Blockaid's detection of the incident through on-chain monitoring, before many of the affected programs had issued any public communication, points to a meaningful gap in the standard security posture of programs built on shared contract infrastructure. Real-time on-chain monitoring is not a substitute for fixing the contract flaw, but it is a necessary component of any response capability. A program that relies on off-chain discovery of an on-chain attack - through user reports, social media, or manual review - will always respond too slowly to limit the blast radius. Automated on-chain monitoring that can pause a contract or alert a multisig on anomalous withdrawal patterns is a baseline expectation for any program that holds user funds in a shared contract. In this case, the attacker drained 2,321 confirmed accounts before the incident was public. That number is not bounded by the speed of the attack; it is bounded by the speed of detection and response.
- 01CoinDesk, $1.1 million crypto card hack crashes neobank token 49%
- 02Pyramid Ledger, Rain contract bug drains $1.1M from self-custodial crypto cards
- 03Crypto.news, Rain contract exploit drains $1.1M from card users
- 04Blockaid, $1.1M Rain ecosystem exploit and onchain monitoring lessons
- 05Gadgets 360, Smart contract exploit drains $1.1M from Rain card users
- 06Gizmo Times, Avici Rain card exploit Solana vulnerability explained
- 07CoinCentral, Crypto card hack drains $1.1M and sends AVICI token to record low
- 08Binance Square, Rain exploit drains about $1.1M from Solana crypto debit card infrastructure