Summary
On August 13, 2024 the Vow (Vowcurrency) protocol lost about $1.2 million (~452 ETH) when its own admin temporarily misconfigured a price setter and an MEV bot pounced. Vow's usdRateSetter admin key called setUSDRate and changed the VOW-to-vUSD exchange rate from 1 to 100 - the team later said it was testing the rate-setter while preparing a lending pool - then reverted it. The function had no input validation and no rate-change delay or timelock, and the inflated rate was readable on-chain for the window between the two transactions. An attacker-controlled MEV bot, its contract deployed 110 days earlier and funded via Tornado Cash, detected the change and within two blocks swapped VOW into vUSD at the 100x rate, minting roughly 148.7 million vUSD far above its backing, then dumped it for ETH and USDT on Uniswap. The VOW token fell 80-87%. The root cause was an unbounded, unprotected privileged setter exposed without a timelock, turning a careless admin action into instantly exploitable on-chain state.
How to avoid it in your code
- Put privileged parameter changes (exchange rates, oracle values, mint controls) behind a multisig and a timelock so no single key can flip them instantly.
- Bound and validate setter inputs; reject implausible values such as a 100x rate change in a single call.
- Never test rate or oracle setters against live, exploitable production state; use a fork or testnet.
- Assume any exploitable on-chain state will be front-run by MEV bots within blocks - there is no safe 'temporary' misconfiguration.
- Monitor admin parameter changes and add a pause path that triggers on anomalous rate or supply movements.
References
Related vulnerabilities
All Web3 →- CRITICALWEB3-PICKLE-2020
On 21 November 2020 Pickle Finance lost about $19.7 million (roughly 19,759,355 DAI worth of cDAI) drained from its pDAI Jar strategy. The ControllerV4 contract exposed swapExactJarForJar(), which moved tokens between Jars but never verified that the supplied Jar addresses were legitimate, protocol-deployed Jars; there was no whitelist check. The attacker deployed malicious EvilJar contracts implementing the expected interface (token, getRatio, balanceOf, withdraw, deposit), and passed them as the swap source and destination, so the controller withdrew from the real strategy into attacker-controlled contracts. The exploit was compounded by an approved converter whose add_liquidity() built a call from user-controlled callData, enabling code injection, and by the strategy treating cDAI as dust; chaining these let the attacker route the strategy's ~19M cDAI out through the fake Jar's deposit() and redeem it for DAI.
- CRITICALWEB3-KILOEX-2025
On April 14, 2025 the perpetuals DEX KiloEx lost about $7.5 million across BNB Chain, Base, opBNB, and Taiko to what was reported as oracle price manipulation but was really an access-control failure. KiloEx's price feed (KiloPriceFeed.setPrices) was meant to be reachable only through a keeper-gated call chain, but the top-level MinimalForwarder.execute function was publicly callable and validated an attacker-supplied signature against attacker-supplied data, letting anyone forge a trusted call that reached setPrices and write an arbitrary price. The attacker set a market price far below true value, opened a leveraged position, then set the price far above value and closed it in the same flow, extracting fabricated profit from the vault; the sequence was repeated across all four chains, with a single transaction netting $3.12M. Reporting that framed it as flash-loan oracle manipulation was imprecise: no market liquidity was moved, the price was simply written directly through the unprotected forwarder. After KiloEx offered a 10% (~$750K) whitehat bounty and no legal action, the attacker returned essentially all of the funds by April 18, 2025.
- CRITICALWEB3-ABRACADABRA-2025
In late March 2025 Abracadabra.Money lost about $13 million (roughly 6,260 ETH) on Arbitrum when an attacker abused the GMX V2 gmCauldrons that accept GMX GM liquidity tokens as collateral. GMX deposits are asynchronous, so the attacker submitted deposit orders with unsatisfiable minOut values that GMX rejected, returning the input USDC to the cauldron's order/router contract while the cauldron's accounting still counted that pending position as live collateral. Functions such as sendValueInCollateral removed real tokens during liquidation without clearing inputAmount/minOut state, so orderValueInCollateral kept reporting phantom collateral. Inside a single cook() batch the attacker borrowed MIM against this ghost collateral, self-liquidated to pull out the real returned tokens, and reborrowed, while the end-of-cook solvency check still read the stale inflated collateral value and passed. The accounting bypass let the attacker borrow against effectively non-existent collateral and extract MIM.
- CRITICALWEB3-RADIANT-2024
On October 16, 2024, the cross-chain lending protocol Radiant Capital lost roughly $50M (about $53M across Arbitrum and BSC) after attackers compromised the devices of at least three of its multisig signers. Initial access began September 11, 2024 via a Telegram message spoofing a trusted former contractor, delivering a ZIP with a decoy PDF that was actually a macOS application carrying INLETDRIFT backdoor malware. The malware sat between the signers' browsers and their hardware wallets, so the Safe (Gnosis) UI and Tenderly simulations displayed correct data while the signers blind-signed a malicious transferOwnership() call on the LendingPoolAddressesProvider contract; the 3-of-11 threshold was met and the attacker then upgraded the pools to a malicious implementation and drained them. Mandiant assessed with high confidence the attack was conducted by North Korea-linked UNC4736 (aka Citrine Sleet/AppleJeus), part of the Lazarus cluster. Funds were not recovered and the protocol later wound down.
- CRITICALWEB3-UWULEND-2024
On June 10, 2024, UwU Lend, an Aave-fork lending protocol on Ethereum, lost about $19.3 million, followed by a second ~$3.7 million drain on June 13, 2024 (combined ~$23 million). The root cause was flash-loan oracle manipulation of the sUSDe price feed: the custom sUSDePriceProviderBUniCatch oracle priced sUSDe as the median of 11 sources, 5 of which read instantaneous Curve pool spot prices via get_p (no TWAP/EMA smoothing) across the FRAXUSDe, USDeUSDC, USDeDAI, USDecrvUSD and GHOUSDe pools. Using a roughly $3.8 billion flash loan, the attacker swapped large USDe amounts to suppress the median sUSDe price, set up positions, then reversed the swaps to inflate it, rendering their own leveraged position liquidatable and self-liquidating repeatedly to harvest base assets at favorable rates. Curve explicitly advises against using get_p spot reads for oracles. The June 13 follow-up reused collateral left from the first attack, since sUSDe was not disabled as borrowable collateral.
- CRITICALWEB3-VELOCORE-2024
On June 2, 2024, the DEX Velocore was drained of about $6.8 million from its constant-product (volatile) pools on Linea and zkSync Era. The root cause combined a missing access-control modifier with an unchecked arithmetic underflow in the ConstantProductPool fee math: velocore__execute performed Vault-only state changes but had no onlyVault check, so anyone could call it directly. The pool's feeMultiplier, which increases per withdrawal and resets each block to deter free swaps, fed an effective fee computed as fee1e9 * feeMultiplier / 1e9 with no upper bound and inside an unchecked block. By repeatedly invoking velocore__execute to inflate feeMultiplier, the attacker drove effectiveFee1e9 above 100% (> 1e9), so the growth term 1e18 - ((1e18 - k) * effectiveFee1e9) / 1e9 underflowed and wrapped to a huge unsigned value, causing a small single-token withdrawal to be accounted as a massive deposit and mint excessive LP tokens. Linea controversially paused its sequencer for about an hour to stop the remaining funds from bridging out.