DEX vulnerabilities in disclosed bug bounty reports
Automated market makers hold liquidity and publish a price, which makes them both a target and the instrument used against other protocols.
- Reports indexed
- 98
- Total paid
- $1.2M
- Critical
- 1
- Largest payout
- $900k
A DEX is an invariant plus a pool of assets, and almost every finding is a way to push the invariant somewhere it was not meant to go: rounding that favours the swapper, fee accrual that can be zeroed, callback hooks in concentrated-liquidity designs that re-enter mid-swap, and router paths that trust a user-supplied token list.
Just as often the DEX is not the victim. Its spot price is read by a lending market, its LP token is valued by a vault, and a pool with thin liquidity becomes the cheapest lever available against a much larger protocol.
Reports here pair naturally with the price manipulation and oracle manipulation categories.
What reviewers look for
- Invariant checks skipped or performed before external interaction
- Router paths accepting arbitrary intermediate tokens
- Swap callbacks re-entering pool state
- Rounding direction favouring the caller
- Pool depth low enough to move within a single transaction
Curated highlights
The largest disclosed payouts in this group, with our own summary of each. Every report links back to the original disclosure.
Spot TWAP oracle manipulated via single-block flash loan
A perpetual derivatives protocol relied on a Uniswap V3 TWAP oracle whose pool observation cardinality was capped at 12, severely reducing its intended 30-second time-weighted average window. An attacker executed a single-block flash loan to heavily distort the underlying spot price without triggering any secondary price feed validation. This allowed the attacker to open oversized leveraged positions at an artificial mark price and force liquidations against counterparties in a single atomic transaction.
Unchecked arithmetic in Move coin split enables balance underflow
A custom coin-splitting helper in a Move-based decentralized exchange implemented unsafe u128 downcasting that bypassed native Move checked arithmetic. Combined with a stale balance check preceding an internal callback, an attacker could request a swap amount exceeding their actual balance. The resulting u128 subtraction underflow truncated upon downcasting into a valid u64 value, crediting the attacker with an artificially inflated balance that could subsequently be drained from the exchange.
Flash-loanable veToken balance inflates emissions gauge weights
A design flaw in the gauge voting system allowed real-time veToken balance checks instead of utilizing checkpointed block or epoch snapshots. An attacker could execute a flash loan to acquire governance tokens, temporarily lock them to generate veToken voting power, vote to direct reward emissions toward their target gauge, and release the lock to repay the flash loan within the same block. This enabled uncollateralized, risk-free manipulation of protocol reward distributions.
Oracle-free AMM invariant rounding allows slow drain
A directional rounding flaw in the Newton-Raphson solver for a StableSwap invariant enabled subtle value extraction during token exchanges. When computing invariant values and target balances, both routines rounded down, yielding an extra wei of token output to the user on specific balance ratios. On low-fee Layer 2 blockchains, an automated script could execute high-frequency minimal swaps to steadily extract pool reserves over time.
Good Entry: V3 Proxy does not send funds to the recipient, instead it sends to the msg.sender
Good Entry's V3 proxy wrapper exposes swap functions intended to be compatible with the Uniswap V2 interface, but these functions ignore the caller-supplied destination address and instead route output tokens to msg.sender. Any caller who passes a different `to` address loses the economic value of the swap — for instance a user blacklisted on the output token, or one whose allowance/signature was compromised and who tries to divert proceeds to a safe address, ends up with funds sent back to the caller. The issue was confirmed by the protocol and the judge rated it Medium; the final fix added an explicit `require(msg.sender == to)` to enforce that swaps only ever go to the caller, which is safe for the OPM-only usage the module was designed for.
Rubicon: Incorrect fee handling in `Position.sol's` Market `Buy`/`Sell` functions
Rubicon's `Position.sol` helpers `_marketBuy` and `_marketSell` pre-calculate the market fee and inject it into their order sizing before routing through `RubiconMarket`, which already accounts for the same fee on v2 trades. The result is double (incorrect) fee accounting that yields improper fee deductions and wrong trade execution whenever a user opens or closes a leveraged position via the swap path. The sponsor confirmed fees should not be handled in these helpers, and the judge reduced the severity to Medium after noting that the wider `RubiconMarket` fee logic contains many errors. The finding was reported by many participants and consolidated as a duplicate group led by issue #282.
All reports in this group
- Superposition: Unintended under/overflow of the amount already swapped in/out due to unmatching logicInteger overflow/underflow$0
- Superposition: Volatile pools with higher fee structure cannot be created because of tick_spacingLogic error$0
- Superposition: Missing `lower<upper` check in `mint_position`Integer overflow/underflow$0
- Superposition: Position's owed fees should allow underflow but it reverts instead, resulting in locked fundsInteger overflow/underflow$0
- Superposition: Parameter misordering in fee collection function causes denial of service and fee lossLogic error$0
- Superposition: When performing `swap` and the swap position does not cover `swap amount`, the base price of `sqrt_price` is set incorrectlyLogic error$0
- Superposition: `swapOut` functions have invalid slippage check, causing user loss of fundsLogic error$0
- Superposition: `_onTransferReceived()` does not work as intendedLogic error$0
- Superposition: `swap_2` implementation will randomly revert due to improper check, root cause for failed test `ethers_suite_uniswap_orchestrated_uniswap_two`Logic error$0
- Superposition: Wrong liquidity formula usedLogic error$0
- Superposition: Lp's liquidity may be lost if re-org happensPrice manipulation$0
- Superposition: If liquidity is insufficient, users may need to pay more tokens in `swap2`Logic error$0
- Phi: `shareBalance` bloating eventually blocks curator rewards distributionLogic error$0
- Phi: Attacker can DOS user from selling shares of a `credId`Front-running / MEV$0
- Phi: Cred creator could cause stuck fundsAccess control$0
- Phi: Reentrancy in creating Creds allows an attacker to steal all Ether from the Cred contractReentrancy$0
- TraitForge: Lack of ability to make an some external function calls makes the DAO stage unreachableReentrancy$0
- Basin: Incorrectly assigned `decimal1` parameter upon decodingInteger overflow/underflow$0
- Basin: For extreme ratios, `getRatiosFromPriceSwap` will return data for which is impossible to converge into a reserveLogic error$0
- Basin: In `Stable2LUT1::getRatiosFromPriceLiquidity`, in extreme cases, `updateReserve` will start breakingInteger overflow/underflow$0
- Optimism: The LPP challenge period can cause malicious and freeloader claims to be uncounterable and can also cause freeloader claims to be abused to entrap honest challengersOracle manipulation$0
- Olas: Changing VoteWeighting contract can result in lost staking incentivesFlash loan attack$0
- Olas: Less active nominees can be left without rewards after an year of inactivityGovernance attack$0
- Thorchain: Incorrect call argument in `THORChain_Router::_transferOutAndCallV5`, leading to grief/steal of `THORChain_Aggregator`'s funds or DoSInteger overflow/underflow$0
- Thorchain: Due to the use of `msg.value` in for loop, anyone can drain all the funds from the `THORChain_Router` contractReentrancy$0
- Predy: Incorrect price for negative ticks due to lack of rounding downOracle manipulation$0
- Predy: Reallocation incorrectly sends the exceed `quoteTokens` to Market contract instead of reallocatorLogic error$0
- Panoptic: Removed liquidity can overflow when calling `SemiFungiblePositionManager.mintTokenizedPosition` functionReentrancy$0
- Panoptic: `PanopticFactory` uses spot price when deploying new pools, resulting in liquidity manipulation when mintingOracle manipulation$0
- Panoptic: When Burning a Tokenized Position `validate` should be done before flipping the `isLong` bits in `_validateAndForwardToAMM()`Logic error$0
- BakerFi: Multiple swap lack slippage protectionOracle manipulation$0
- LoopFi: Availability of deposit invariant can be bypassedFront-running / MEV$0
- Renzo: Lack of slippage and deadline during withdraw and depositOracle manipulation$0
- Revert Lend: Users cannot stop loss in AutoRange and AutoExitOracle manipulation$0
- Revert Lend: `V3Utils.execute()` does not have caller validation, leading to stolen NFT positions from usersAccess control$0
- Revert Lend: User might execute `PositionToken` of token set by previous token ownerAccess control$0
- Revert Lend: `AutoRange` execution can be front-ran to avoid protocol fee, causing loss for protocolFront-running / MEV$0
- Abracadabra Money: Adjusting "_I_" will create a sandwich opportunity because of price changesFront-running / MEV$0
- Abracadabra Money: Attacker can amplify a rounding error in MagicLP to break the I invariant and cause malicious pricingReentrancy$0
- Abracadabra Money: Less base tokens are transferred when selling quote tokens due to the precision loss that occurred in `_GeneralIntegrate()`Integer overflow/underflow$0
- Abracadabra Money: Missing Return Statement in `_getReserves` Function in `MagicLpAggregator` ContractOracle manipulation$0
- Abracadabra Money: Anyone making use of the MagicLP's TWAP to determine token prices will be exploitable.Oracle manipulation$0
- Abracadabra Money: Pool Creation Failure Due to WETH Transfer Compatibility Issue on Some ChainsOracle manipulation$0
- Abracadabra Money: Users who deposited MIM and USDB tokens into BlastOnboarding may incur losses when the pool is created via bootstrapReentrancy$0
- Taiko: Gas issuance is inflated and will halt the chain or lead to incorrect base feeLogic error$0
- Salty.IO: MinShares Slippage Parameters Are Ineffective For Initial DepositFront-running / MEV$0
- Salty.IO: formPOL lacks slippage and deadline protectionOracle manipulation$0
- Salty.IO: Suboptimal arbitrage implementationInteger overflow/underflow$0
- Salty.IO: Incorrect assumption in PoolMath.sol can cause underflow when zapping is usedInteger overflow/underflow$0
- Collective: positionMapping for last element in heap is not updated when extracting max elementLogic error$0
- Collective: MaxHeap.sol: Already extracted tokenId may be extracted againLogic error$0
- Olas: Permanent DOS in `liquidity_lockbox` for under $10Logic error$0
- Olas: Missing slippage protection in `liquidity_lockbox::withdraw`Front-running / MEV$0
- Open Dollar: Unable to retrieve price information with CamelotRelayer contractOracle manipulation$0
- Tapioca DAO: `BaseTOFTLeverageModule.sol`: `leverageDownInternal` tries to burn tokens from wrong addressGovernance attack$0
- Tapioca DAO: TOFT and USDO Modules Can Be SelfdestructedGovernance attack$0
- Tapioca DAO: Potential 99.5% loss in `emergencyWithdraw()` of two Yieldbox strategiesFront-running / MEV$0
- Tapioca DAO: TOFT leverageDown always fails if TOFT is a wrapper for native tokensGovernance attack$0
- Centrifuge: ```trancheTokenAmount``` should be rounded UP when proceeding to a withdrawal or previewing a withdrawalLogic error$0
- Centrifuge: `LiquidityPool::requestRedeemWithPermit` transaction can be front run with the different liquidity poolLogic error$0
- Maia DAO Ecosystem: Many `create` methods are suspicious of the reorg attackGovernance attack$0
- Maia DAO Ecosystem: Incorrect flow of adding liquidity in `UlyssesRouter.sol`Reentrancy$0
- Maia DAO Ecosystem: `UlyssesToken.setWeights(...)` can cause user loss of assets on vault deposits/withdrawalsGovernance attack$0
- Maia DAO Ecosystem: `UlyssesPool.sol` does not match `EIP4626` because of the preview functionsGovernance attack$0
- Maia DAO Ecosystem: The `RestakeToken` function is not permissionlessAccess control$0
- Maia DAO Ecosystem: Removing a `UniswapV3Gauge` via `UniswapV3GaugeFactory` does not actually remove it from the `UniswapV3Staker`. The gauge still gains rewards and can be staked too (even though deprecated). Plus old stakers can game the rewards of new stake…Governance attack$0
- Maia DAO Ecosystem: `withdrawProtocolFees()` Possible malicious or accidental withdrawal of all rewardsAccess control$0
- Maia DAO Ecosystem: `TalosBaseStrategy#init()` lacks slippage protectionReentrancy$0
- Maia DAO Ecosystem: `setWeight()` Logic errorReentrancy$0
- Maia DAO Ecosystem: `UlyssesToken` asset ID accounting errorInteger overflow/underflow$0
- Maia DAO Ecosystem: Removing a `BribeFlywheel` from a Gauge does not remove the reward asset from the rewards depo, making it impossible to add a new Flywheel with the same reward tokenAccess control$0
- Maia DAO Ecosystem: `Rerange`/`rebalance` should not use `protocolFee` as an asset for adding liquidityReentrancy$0
- Maia DAO Ecosystem: `VirtualAccount` cannot directly send native tokensGovernance attack$0
- Maia DAO Ecosystem: Deploy flow of `Talos` is brokenGovernance attack$0
- Maia DAO Ecosystem: Some functions in the Talos contracts do not allow user to supply `slippage` and `deadline`, which may cause swap revertFront-running / MEV$0
- Maia DAO Ecosystem: Slippage controls for calling `bHermes` contract's `ERC4626DepositOnly.deposit` and `ERC4626DepositOnly.mint` functions are missingInteger overflow/underflow$0
- Maia DAO Ecosystem: `BribesFactory::createBribeFlywheel` can be completely blocked from creating any `Flywheel` by a malicious actorAccess control$0
- Maia DAO Ecosystem: A lack of slippage protection can lead to a significant loss of user fundsFront-running / MEV$0
- Maia DAO Ecosystem: A user can bypass bandwidth limit by repeatedly "balancing" the poolGovernance attack$0
- Maia DAO Ecosystem: An attacker can exploit the "deposit" to drain the `Ulysess Liquidity Pool`Integer overflow/underflow$0
- Maia DAO Ecosystem: Second per liquidity inside could overflow `uint256` causing the LP position to be locked in `UniswapV3Staker`Integer overflow/underflow$0
- Lybra Finance: `EUSD.mint` function wrong assumption of cases when calculated sharesAmount = 0Governance attack$0
- Lybra Finance: Incorrectly implemented modifiers in `LybraConfigurator.sol` allow any address to call functions that are supposed to be restrictedAccess control$0
- Asymmetry Finance: Division before multiplication truncate `minOut` and incurs heavy precision loss and result in insufficient slippage protectionAccess control$0
- Asymmetry Finance: Missing derivative limit and deposit availability checks will revert the whole `stake()` functionAccess control$0
- Asymmetry Finance: Lack of deadline for uniswap AMMFront-running / MEV$0
- Asymmetry Finance: Possible DoS on `unstake()`Oracle manipulation$0
- Asymmetry Finance: `WstEth` derivative assumes a `~1=1` peg of stETH to ETHOracle manipulation$0
- Asymmetry Finance: Reth `poolPrice` calculation may overflowOracle manipulation$0
- Asymmetry Finance: Staking, unstaking and rebalanceToWeight can be sandwiched (Mainly rETH deposit)Oracle manipulation$0
- Asymmetry Finance: Non-ideal rETH/WETH pool used pays unnecessary feesGovernance attack$0
- Asymmetry Finance: Potential `stake()` DoS if sole safETH holder (ie: first depositor) unstakes `totalSupply` - 1Logic error$0