HACK ANALYSIS 4 min read

NumaMoney Hack Analysis


NumaMoney Hack Analysis

Overview:

On April 18, 2025, the Numa protocol (@numamoney), a non-custodial and decentralized LST-backed synthetics protocol on the Arbitrum ($ARB) chain, suffered a sophisticated exploit. The attacker leveraged a price manipulation scheme using a flash loan from Aave V3, Balancer Vault and Uniswap V3 pools. The exploit targeted the NumaVault contract, manipulating the NUMA token price to enable excessive borrowing and collateral withdrawal, stealing ~$527,328 from the victim address. This vulnerability falls under OWASP SC02:2025 Price Oracle Manipulation.

Numa’s official response confirms the price manipulation, collateral removal, and ongoing investigation. Read more- here.

Smart Contract Hack Overview:

Fig: Attack Transaction

Decoding the Smart Contract Vulnerability:

  • The root cause of the NumaMoney exploit lay in a critical lack of real-time price validation and slippage protection within the NumaVault contract’s sell() function. This flaw allowed the attacker to manipulate the last_lsttokenvalueWei variable using a massive flash loan, bypassing the protocol’s zero-slippage trading promise.
Fig: Vulnerable sell() function
  • The lockNumaSupply() function—intended to stabilize native yield—was exploited to freeze the manipulated price, amplifying the attack.
Fig: lockNumaSupply() function
  • Additionally, NumaMoney’s reliance on internal NumaPriceOracleNew data without external validation left it vulnerable to this sophisticated flash loan attack.
  • Both functions rely on INumaVault methods (numaToLst() and lstToNuma()), which use the manipulated last_lsttokenvalueWei from sell(). The absence of external oracle integration creates a circular dependency, allowing the skewed price (trace shows a shift from 148,850,422,003,959 to 116,943,924,501,586 post-sell()) to propagate without validation. The FullMath.mulDivRoundingUp() rounding further favored the attacker by inflating borrowed asset values.
Fig: Vulnerable NumaPriceOracleNew Contract
  • The attacker called sell() with a massive NUMA amount, skewing last_lsttokenvalueWei. This propagated to NumaPriceOracleNew, enabling downstream exploitation. The lack of real-time checks was the entry point.
  • During the flash loan, lockNumaSupply(true) was invoked, ensuring the skewed last_lsttokenvalueWei persisted, preventing yield-driven rebalancing.
  • After the price manipulation and freezing, the attacker redeemed rETH using CNumaLst.redeemFresh(), exploiting the inflated exchange rate from the manipulated NumaPriceOracleNew data. They then donated 150 rETH to the vault, further skewing the $NUMA price to facilitate profit extraction, and repurchased 85,511 $NUMA via NumaVault.buyNoMax() at the artificial price, locking in approximately $529,102.12 in profits.

Attack Flow:

Flash Loan and Deposit: The attacker secured 3,760 rETH and 631,422 $NUMA via flash loans (Aave V3, Balancer, Uniswap V3, apNUMA), deposited rETH into Numa, and minted crEth using NumaComptroller.enterMarkets, exploiting the lack of flash loan safeguards.

Borrowing and Transfer: They borrowed 3,626,482 $NUMA via CNumaLst.borrowFreshNoTransfer, which lacked supply caps and relied on manipulable vault.getMaxBorrow() pricing from NumaPriceOracleNew, transferring it to Address #2 (0x8594a) to mint cNUMA, repeated five times.

Price Manipulation and Freezing: Then, the attacker borrowed another 3,626,482 $NUMA, called NumaVault.sell() to crash the price (exploiting no slippage protection in last_lsttokenvalueWei), propagated the skewed price to NumaPriceOracleNew via vault.numaToLst(), donated 150 rETH to manipulate further, and froze it with lockNumaSupply(true).

Redemption and Repurchase: They redeemed 283 rETH via CNumaLst.redeemFresh, exploiting inflated exchangeRateStoredInternal(), repurchased 85,511 $NUMA with NumaVault.buyNoMax, and Address #2 redeemed remaining collateral, mischaracterized as liquidation.

Final Extraction and Laundering: Address #2 borrowed 131 rETH, and the attacker swapped assets to ETH, bridged them via zkBridge/Meson, and deposited them into Tornado Cash, exploiting the lack of withdrawal monitoring.

Mitigation and Best Practices:

  • To mitigate future exploits, NumaMoney should integrate reputed oracles into NumaPriceOracleNew for real-time price validation, add slippage protection to NumaVault.sell() to prevent price crashes, and implement circuit breakers to halt trading during anomalies.
  • Introduce strict supply caps and per-block mint/borrow limits in CNumaLst.borrowFreshNoTransfer() and buyNoMax() to restrict how much synthetic $NUMA can be minted or borrowed per transaction or block.
  • Add a circuit breaker mechanism to halt trading (e.g., sell/mint/borrow/redeem) if price deviation exceeds a configured threshold, triggered on abnormal movement of last_lsttokenvalueWei or exchange rates.
  • To prevent such vulnerabilities, the best Smart Contract auditors must examine the Smart Contracts for logical issues. We at CredShields provide smart contract security and end-to-end security of web applications and externally exposed networks. Our public audit reports can be found on https://github.com/Credshields/audit-reports. Schedule a call at https://credshields.com/
  • Scan your Solidity contracts against the latest common security vulnerabilities with 494+ detections at SolidityScan.
Fig: SolidityScan — Smart Contract Vulnerability Scanner

Conclusion:

SolidityScan is an advanced smart contract scanning tool that discovers vulnerabilities and reduces risks in code. Request a security audit with us, and we will help you secure your smart contracts. Signup for a free trial at https://solidityscan.com/signup

Follow us on our Social Media for Web3 security-related updates.

SolidityScan — LinkedIn | Twitter | Telegram | Discord