Résumé
On 27 January 2022 the Qubit Finance QBridge, connecting Ethereum and BNB Smart Chain, was exploited for about $80 million (roughly 206,809 BNB). The bug lived in a deprecated deposit() function on the Ethereum-side QBridge that remained active after a newer depositETH() path was introduced for native ETH. The legacy deposit() expected an ERC-20 token address but did not validate it against address(0); it called tokenAddress.safeTransferFrom(depositor, address(this), amount) using SafeERC20, and because address(0) has no code the low-level call to a non-contract address returned success without reverting, so safeTransferFrom silently passed while transferring nothing. The function then emitted a Deposit event as if real ETH had arrived. The BSC-side relayer trusted that event and minted qXETH collateral (the attacker obtained around 77,162 qXETH), which the attacker pledged as collateral to borrow out the bridge's deposited assets and convert them to BNB, all without ever locking real value.
Comment l’éviter dans votre code
- Validate that user-supplied token addresses are not address(0) and are on an allowlist before any transfer or credit
- Require that low-level/SafeERC20 transfer targets contain code (extcodesize > 0); a call to a codeless address returns success
- Remove deprecated functions outright when migrating; never leave a legacy deposit path callable alongside its replacement
- Separate native-asset and ERC-20 deposit logic so native value is checked via msg.value, not a token transfer
- Have bridge relayers verify the actual on-chain balance delta, not just the emitted Deposit event, before minting
Références
Vulnérabilités liées
Tout Web3 →- 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.
- HIGHWEB3-VOW-2024
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.
- 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-INVERSE-2022
On 2 April 2022 Inverse Finance lost approximately $15.6 million on Ethereum when an attacker manipulated the INV price oracle feeding its Anchor money market. INV was priced by a Keep3r TWAP over the SushiSwap INV/ETH pair, but the oracle only folded a new price cumulative into the average when the elapsed time exceeded its 30-minute period, so shortly after a fresh update the oracle effectively returned the current manipulable spot price instead of a true time-weighted average. Using about 500 ETH of their own funds (no flash loan), the attacker bought INV on SushiSwap and routed ETH through Curve and DOLA into more INV, draining the thin INV/ETH pool and spiking the reported INV price, then deposited the inflated INV as collateral and borrowed ETH, WBTC, DOLA and YFI far exceeding its real value. The root cause was a TWAP whose update window let a single-block spot manipulation pass through as the reported price.
- CRITICALWEB3-WORMHOLE-2022
On February 2, 2022, the Wormhole Solana-Ethereum bridge was exploited for about $326 million (120,000 wETH). On Solana, Wormhole's core bridge confirmed guardian signatures by reading the Instructions sysvar to verify that the Secp256k1 verification instruction had run, but its verify_signatures function received the sysvar as a caller-supplied account and called load_instruction_at against it without checking that the account's address equaled the genuine Instructions sysvar (solana_program::sysvar::instructions::id()). The attacker passed a spoofed account crafted to mimic a successful verification of fabricated guardian signatures, so the program accepted a forged VAA and minted 120,000 wETH with no Ethereum collateral, bridging roughly 93,750 ETH back to Ethereum. The real fix added an explicit address check rejecting any instruction account whose key did not match the sysvar id. Jump Crypto (parent of Wormhole developer Certus One) replaced the full 120,000 ETH the next day to keep the bridge solvent; about $225 million was later clawed back via an English High Court order in February 2023.
- CRITICALWEB3-COMPOUND-2021
On 29 September 2021 Compound executed governance Proposal 062, which upgraded the Comptroller to split COMP reward distribution into separate supply-side and borrow-side speeds, and the upgrade introduced an accounting bug that left roughly $80–150 million in COMP erroneously claimable. In distributeSupplierComp, the guard meant to seed a new supplier's index used the wrong comparison operator: it read if (supplierIndex == 0 && supplyIndex > compInitialIndex) instead of >=. For markets where a user supplied while supplyIndex still equaled compInitialIndex (1e36, e.g. unmigrated markets), the branch failed to fire, so supplierIndex stayed 0 while the global index was 1e36, producing a deltaIndex of 1e36 and crediting that supplier with COMP as if the entire index had accrued to them. The unprotected drip() function could be called repeatedly to push the over-accrued COMP into the Comptroller for claiming. Proposal 064 (executed around 9 October 2021) patched the logic.