Back to Blog

Revisiting the CashioApp Security Incident

Code Auditing
May 16, 2022

Started at March-23–2022 16:20:08 UTC+8, CashioApp was exploited to drain the collateral token account at the loss about 52 millions. The hack was made possible due to the insufficient check of input accounts that allows the attacker to mint 20 billion $CASH tokens without any deposit. In the following, we show the technical details.

Summary

The incident was due to a bug in the Brrr program that is designed to handle the minting and burning of $CASH tokens with the collateral of Saber LP Arrows. Specifically, users can print $CASH, which means minting CASH,bydepositing‘Arrow‘LPtokens.NotethatArrowLPtokenreceivethe[SaberLPtoken](https://app.saber.so/swap)astheunderlyingtokens.The‘printcash‘instruction,whichcanmint‘CASH, by depositing `Arrow` LP tokens. Note that Arrow LP token receive the [Saber LP token](https://app.saber.so/swap) as the underlying tokens. The `print_cash` instruction, which can mint `CASH, receives a list of accounts including the Bankaccount and theCollateralaccount. They are used to record and track the collateral (i.e.,ArrowLP tokens) that is allowed to be used for mintingCASH‘.Bydesign,thesetwoaccountsshouldonlybeinitializedandauthorizedbytheadmin.However,theprogramfailstocheckthevalidityofthe‘Bank‘account.Asaresult,theattackercancraftaseriesoffakeaccounts(includingthe‘Bank‘account)tofeedintotheinstruction‘printcash‘,andprint‘CASH`. By design, these two accounts should only be initialized and authorized by the admin. However, the program fails to check the validity of the `Bank` account. As a result, the attacker can craft a series of fake accounts (including the `Bank` account) to feed into the instruction `print_cash`, and print `CASH` for almost free (the only cost is transaction fees).

Details

Let’s start the analysis from the used accounts of instruction print_cash below.

The attribute common (line 75) is a struct whose type is BrrrCommon in the program. In BrrrCommon, the bank account and the collateral account are initialized and authorized by the admin. The crate_token is the account of the $CASH token, which stores information about $CASH, such as the public key of the crate_mint (line 107), the public keys of admin roles, and more. The crate_collateral_tokens is a vault account that holds the collateral tokens transferred from users. Since the collateral should be Arrow LP tokens, which receive the LP tokens of Saber, users have to input the related accounts of saber_swap. The last two attributes in struct BrrrCommon are program IDs of target programs used in the instruction. Note that the last four attributes in struct PrintCash are the user's system account (also the signer of the transaction), the user's collateral account, the user's $CASH token account that receives the minted $CASH, and the pubkey of the account that has the authority to mint the $CASH.

The Attack Transaction

After understanding the functionality of above accounts, we then start to analyze the attack transaction: 0x4fgL…z2K5. This attack is initialzied from the attacker address (located at 0x6D7f) and the list of input accounts in the instruction PrintCash is shown below.

The Account #1 (0x5aha) above corresponds to the Bank account. We noticed that it's different from the address provided on the CashioApp's official website (0xEm1P), which means the validation of Bank account is insufficient!

Validation

Let’s take a closer look at the validation of the struct BrrrCommon in the code to figure out how the bypass works.

The only check of the input Bank account is to ensure the input Collateral account is associated with the Bank account (line 12). However, it can be easily bypassed by providing a fake Collateral account as well. Besides, to avoid paying real collateral assets, the attacker also provided fake saber_swap accounts. Note that the attacker aims to deposit unvaluable collateral assets to print valuable $CASH tokens, so the crate_token and the crate_mint provided by the attacker should be true addresses. In other words, the insufficient check of the Bank account enables the attacker to craft a series of fake accounts to print $CASH with unvaluable collateral.

The Fix

The fix is to add the statement of assert_keys_eq!(self.bank.crate_mint, self.crate_mint). This statement ensures the Bank account's crate_mint is the correct crate_mint for $CASH. However, how does it ensure the Bank account is valid? Let's take a look at the NewBank struct (in program bankman) and the NewCrate struct (in program crate_token) to find the answer.

In fact, the Bank account is a PDA whose seeds contain the address of the crate_token. Meanwhile, the crate_token is also a PDA whose seeds contain the address of the crate_mint. That ensures that the Bank account is valid if the input crate_mint is valid. Without a correct crate_mint, attackers cannot mint the $CASH and cannot launch the attacks.

About BlockSec

BlockSec is a pioneering blockchain security company established in 2021 by a group of globally distinguished security experts. The company is committed to enhancing security and usability for the emerging Web3 world in order to facilitate its mass adoption. To this end, BlockSec provides smart contract and EVM chain security auditing services, the Phalcon platform for security development and blocking threats proactively, the MetaSleuth platform for fund tracking and investigation, and MetaSuites extension for web3 builders surfing efficiently in the crypto world.

To date, the company has served over 300 esteemed clients such as MetaMask, Uniswap Foundation, Compound, Forta, and PancakeSwap, and received tens of millions of US dollars in two rounds of financing from preeminent investors, including Matrix Partners, Vitalbridge Capital, and Fenbushi Capital.

Official website: https://blocksec.com/

Official Twitter account: https://twitter.com/BlockSecTeam

Sign up for the latest updates
Bitget's $387.5M Off-Chain Breach: Beyond Keys and Contracts
Security Insights

Bitget's $387.5M Off-Chain Breach: Beyond Keys and Contracts

On September 24, 2026, attackers exploited a vulnerability in a third-party security product, obtained internal credentials, and forged withdrawal commands. The resulting transfers moved approximately $387.5M from some of Bitget's operational wallets across Ethereum, other EVM networks, XRP Ledger, Zcash, and TRON; private keys and cold wallets remained intact. This deep dive summarizes the disclosed incident path and fund flow, examines rapid conversion into native assets and the ecosystem recovery response, proposes a systematic defense-in-depth framework for institutions, and explains how authorized blockchain penetration testing can validate cross-layer assumptions.

~$11.3M Lost: Multicall Router, Nostra | BlockSec Weekly
Security Insights

~$11.3M Lost: Multicall Router, Nostra | BlockSec Weekly

This report, covering 2026/09/14 - 2026/09/20, examines two security incidents with approximately $11.3M in combined losses, on Ethereum and Starknet. In the larger one, a multicall router accepted its own address as a dispatch target, so the nested call reached the Gateway module of a Safe wallet carrying the router's own already-authorized identity instead of the external caller's, and roughly 2,900 `aEthrsETH` was routed out of that wallet into an attacker-created Uniswap v4 pool. On Starknet, Nostra's oracle integration required a minimum of only one aggregated source, so when only two of the three configured price sources reached the aggregation, a manipulated thin-pool quote averaged with a normal quote to value `NSTR` at roughly $49.52, supporting approximately $3.5M of borrowing against overvalued collateral.

~$320M Lost: Liquid Network, Symbiosis Exploits | BlockSec
Security Insights

~$320M Lost: Liquid Network, Symbiosis Exploits | BlockSec

This report, covering 2026/09/07 - 2026/09/13, examines two security incidents that caused approximately $320M in losses, including the Liquid Network exploit of 2026/09/06 that the previous report did not cover. The larger was that Liquid Network exploit, where the rangeproof validation cache in Elements derived its key by hashing four fields — two of them variable in length — concatenated with nothing marking the boundaries between them, so a verdict recorded for one output was returned for another whose proof was never examined, letting the attacker create 4,000 unbacked L-BTC and peg out nearly all of them as bitcoin. On the Bitcoin route of the Symbiosis cross-chain bridge, spanning BNB Smart Chain, Ethereum and Rootstock, off-chain code that reads Bitcoin deposits took the depositor's identity from a field the depositor controls and then subtracted its fee from the deposit without checking whether the fee itself was negative, letting a 330-satoshi deposit mint `46,116,860,184.27388234 syBTC`; the pools it had to be sold through held only 11.26 syBTC, so the loss to liquidity providers and users came to an estimated 9.97 BTC (~$770K).

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit