Integer overflow, underflow and rounding bugs in disclosed reports
Solidity 0.8 removed the easy overflows. Precision loss, unchecked blocks and casting errors kept the class alive.
- Reports indexed
- 123
- Total paid
- $180k
- Critical
- 0
- Largest payout
- $180k
Built-in overflow checks retired the classic `balance -= amount` underflow, and the class immediately reappeared in three new forms. Explicit `unchecked` blocks added for gas savings reintroduce the original bug with none of the original excuse. Downcasts from `uint256` to `uint128` or `uint64` silently truncate. And on non-EVM chains, Rust release builds wrap on overflow unless the arithmetic is explicitly checked.
The higher-value findings in this class are rounding rather than wrapping. Integer division truncates toward zero, and a protocol that rounds in the user's favour on deposit and again on withdrawal leaks value on every cycle. Share-price vaults are the classic target: the first depositor inflates the share price so that later deposits round down to zero shares.
These bugs are quiet. They rarely revert, they rarely trip monitoring, and they are usually found by writing the invariant down and testing it at the boundaries.
What reviewers look for
- `unchecked` blocks around arithmetic that depends on user input
- Downcasts to smaller integer widths without a bound check
- Division performed before multiplication in a fee or share calculation
- Empty-vault share price paths and first-depositor inflation
- Rust arithmetic without `checked_*` / `saturating_*` in release builds
Curated highlights
The largest disclosed payouts in this group, with our own summary of each. Every report links back to the original disclosure.
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.
Putty: Put options are free of any fees
The Putty protocol contains a logic error where put options bypass the required fee collection mechanism upon exercise. While call options correctly deduct a designated fee, the logic for put options transfers the full strike amount to the exerciser without any fee deduction. This failure results in consistent revenue leakage for the protocol, as put options are currently processed free of charge.
Putty: Options with a small strike price will round down to 0 and can prevent assets to be withdrawn
The Putty protocol contains a vulnerability where certain ERC-20 tokens, which revert on zero-value transfers, can cause a Denial-of-Service during asset withdrawals. The issue occurs because the protocol's fee calculation uses integer division, which can round down to zero for small strike prices and low fee rates. When the contract attempts to transfer this zero-value fee to the protocol's treasury, the transaction reverts, permanently locking the user's assets within the vault.
Rigor Protocol: Missing upper limit definition in `replaceLenderFee()` of `HomeFi.sol`
Rigor Protocol's HomeFi contract exposes `replaceLenderFee()`, an admin-only setter that stores `lenderFee` as an unbounded uint256 with only a no-change guard. Because newly created projects inherit their `lenderFee` from the HomeFi contract, a malicious or compromised admin can set it to an extreme value such as `type(uint256).max`. When a community then lends to such a project via `lendToProject()`, the fee formula `(_lendingAmount * lenderFee) / (lenderFee + 1000)` overflows in its multiplication step and reverts, permanently blocking lending to any project created afterward. The sponsor confirmed the finding, and the recommended fix is an upper-bound check on the fee inside `replaceLenderFee()`.
The Graph: After proposed 0.8.0 upgrade kicks in, L2 `finalizeInboundTransfer` might not work
The Graph's L2GraphTokenGateway restricts finalizeInboundTransfer to calls arriving from its L1 counterpart gateway, verified via applyL1ToL2Alias, which intentionally wraps the L1 address plus a fixed offset into the expected L2 sender. The protocol planned to upgrade from Solidity 0.7.6 to 0.8.0, whose built-in overflow checks would cause that deliberate uint160 wrap to revert whenever the sum exceeds UINT160_MAX. Because the L1 gateway's address can trigger such an overflow, the modifier would reject legitimate inbound transfers after the upgrade and break L2 deposit finalization. The sponsor confirmed the concern, the judge upheld it as a valid Medium, and the fix wrapped the aliasing arithmetic in an unchecked block in a future 0.8.0 branch.
PoolTogether: Silent overflow could alter computation when calculating the `vaultPortion` in the `PrizePool` contract
The PrizePool contract in the PoolTogether V5 protocol contains an unsafe type conversion flaw that can lead to silent integer overflows. During the calculation of a vault's portion of prizes, contribution metrics returned as uint256 are cast to int256 without bound checks. If these contributions are sufficiently large, the overflow results in mathematically incorrect reward distribution, negatively impacting the prize yields for specific draws.
All reports in this group
- PoolTogether: Loss of precision leads to under-collateralizedInteger overflow/underflow$0
- Current Finance: Multiply-before-divide overflow in update_pool_reward_manager permanently freezes all lending operations for affected CoinTypeInteger overflow/underflow$0
- Centrifuge Protocol V3.1: Incorrectly handled subtraction leads to underflow resulting in permanent user fund lock and DOSInteger overflow/underflow$0
- Dango DEX: Inconsistent multiplication during order creation and cancellation can lead to panics and Denial of Service during order cancellationInteger overflow/underflow$0
- Brevis Pico ZKVM: Missing `offset` check will cause integer overflow violating ELF specificationInteger overflow/underflow$0
- Dango DEX: User can pause all auctions by overflow in mid-price averageInteger overflow/underflow$0
- Dango DEX: Users may fail to add liquidity because of overflowInteger overflow/underflow$0
- Ammplify: Borrow fee uses APY as per-second rate, causing extreme overchargingInteger overflow/underflow$0
- Ammplify: Utilization Ratio Overflow Due to Incorrecte uint64 CastInteger overflow/underflow$0
- Ammplify: Shift-Overflow in getEquivalentLiq Inflates LP SharesInteger overflow/underflow$0
- Ammplify: User can lose all funds when creating or increasing compounded Maker position due to share inflation first deposit attack in any segment of the user's rangeInteger overflow/underflow$0
- BMX Deli Swap: Attacker can swap wBTC in the DeliHook multiples times to not pay / pay less swap feesInteger overflow/underflow$0
- Malda: Wrong direction of rounding in redeem may lead to drain if exchange rate grows largeInteger overflow/underflow$0
- Notional Exponent: DoS might happen to `DineroWithdrawRequestManager#_initiateWithdrawImpl()` due to overflow on `++s_batchNonce`Integer overflow/underflow$0
- Burve: Reserve Share Overflows Due to Too Strict Reward Calculation MechanismInteger overflow/underflow$0
- Yieldoor: `Vault::_calcDeposit()` will overflow for low priced tokensInteger overflow/underflow$0
- Yieldoor: Integer overflow in observation index calculation leads to denial of serviceInteger overflow/underflow$0
- Rubicon: Due to the loss of precision, `openPosition` will make the user's leverage higher than expectedInteger overflow/underflow$0
- Rubicon: Attack on rounding errors to get risk free profitInteger overflow/underflow$0
- LoopFi: Rewards might be lost due to the error that `_updateRewardIndex()` might advance `lastBalance` without advancing index for a tokenInteger overflow/underflow$0
- Plaza Finance: Approval overflow causes DoS in `BalancerRouter`'s `exitPlazaAndBalancer`Integer overflow/underflow$0
- Plaza Finance: Rounding loss in Auction#slotSize allows malicious user to force auction to be undersoldInteger overflow/underflow$0
- Autonomint Colored Dollar V1: Total cds deposited amount is incorrectly modified when cds depositor is at a loss, leading to stuck USDaInteger overflow/underflow$0
- Kakarot: Prover can cheat in `felt_to_bytes_little` due to value underflowInteger overflow/underflow$0
- Teller Lender Groups Update Audit: Repayer can brick lending functionality of `LenderCommitmentGroup_Smart` by repaying excessInteger overflow/underflow$0
- Kakarot: `decode_legacy_tx` allows validation of signatures with `chain_id` that are larger than felt, and overflowsInteger overflow/underflow$0
- Debita Finance V3: Precision loss leads to locked incentives in `DebitaIncentives::claimIncentives()`Integer overflow/underflow$0
- Debita Finance V3: Borrowers can not extend loans which has maximum duration less than 24 hoursInteger overflow/underflow$0
- Debita Finance V3: The precision loss in the fee percentage for connecting offers results in the borrower paying less than the expected fee.Integer overflow/underflow$0
- Superfluid Locker System: `FluidLocker::_getUnlockingPercentage()` divides before multiplying, suffering a significant precision errorInteger overflow/underflow$0
- Superfluid Locker System: `FluidLocker::_getUnlockingPercentage()` uses 540 instead of `540 days` leading to stuck funds as the unlocking percentage will be bigger than `100%` and underflowInteger overflow/underflow$0
- Mento x Good$ Integration: `GoodDollarExchangeProvider::mintFromExpansion()` will change the price due to a rounding error in the new ratioInteger overflow/underflow$0
- The Wildcat Protocol: User could withdraw more than supposed to, forcing last user withdraw to failInteger overflow/underflow$0
- Superposition: `get_fee_growth_inside` in `tick.rs` should allow for `underflow`/`overflow` but doesn'tInteger overflow/underflow$0
- Superposition: Unintended under/overflow of the amount already swapped in/out due to unmatching logicInteger overflow/underflow$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
- Fenix Finance: `boostedValue` should be added to `permanentTotalSupply` for permanently locked tokensInteger overflow/underflow$0
- Karak: A `DoS` on snapshots due to a rounding error in calculationsInteger overflow/underflow$0
- Flayer: Quorum overflow in `CollectionShutdown` leads to complete drain of contract's fundsInteger overflow/underflow$0
- TraitForge: Imprecise token age calculation results in an incorrect nuke factor, causing users to claim the wrong amountInteger overflow/underflow$0
- Velar Artha PerpDEX: Fee Precision Loss Disrupts Liquidations and Causes Loss of FundsInteger overflow/underflow$0
- Velar Artha PerpDEX: First depositor could DoS the poolInteger overflow/underflow$0
- BendDAO: `isolateRepay()` lack of check `onBehalf == nftOwner`Integer overflow/underflow$0
- BendDAO: Mismatch between yield amount deposited in shares calculation and `getAccountYieldBalance()`Integer overflow/underflow$0
- Basin: Incorrectly assigned `decimal1` parameter upon decodingInteger overflow/underflow$0
- BendDAO: Revert due to underflow error, leading to lock of the liquidated NFTInteger overflow/underflow$0
- Basin: In `Stable2LUT1::getRatiosFromPriceLiquidity`, in extreme cases, `updateReserve` will start breakingInteger overflow/underflow$0
- Sentiment V2: rounding error due to internal accounting and can steal some portion of the first depositors fundsInteger overflow/underflow$0
- Munchables: Miscalculation in `_farmPlots` function could lead to a user unable to unstake all NFTsInteger overflow/underflow$0
- Munchables: in `farmPlots()` an underflow in edge case leading to freeze of funds (NFT)Integer overflow/underflow$0
- Optimism: Multiplication overflow leading to memory corruption and incorrect register write-backInteger overflow/underflow$0
- Olas: Non-normalized amounts sent via Wormhole lead to failure to redeem incentivesInteger overflow/underflow$0
- Olas: Incorrect handling of last nominee removal in `removeNominee` functionInteger overflow/underflow$0
- Thorchain: Incorrect call argument in `THORChain_Router::_transferOutAndCallV5`, leading to grief/steal of `THORChain_Aggregator`'s funds or DoSInteger overflow/underflow$0
- Exactly Protocol Update - Staking Contract: Precision Loss in `notifyRewardAmount` Function Causes Unclaimable RewardTokenInteger overflow/underflow$0
- Gondi: Division before multiplication could lead to users losing 50% in `WithdrawalQueue`Integer overflow/underflow$0
- Panoptic: Premia calculation can cause DOSInteger overflow/underflow$0
- Panoptic: Overflow in `CollateralTracker` allows minting shares for freeInteger overflow/underflow$0
- Panoptic: `removedLiquidity` can be underflowed to lock other user's depositsInteger overflow/underflow$0
- Andromeda – Validator Staking ADO and Vesting ADO: execute_claim() possible loss of accuracy or even inability to retrieve fundsInteger overflow/underflow$0
- Elfi: `isHoldAmountAllowed` and `isSubAmountAllowed` wrong subtraction will result in DoSInteger overflow/underflow$0
- Wise Lending: Precision loss in the calculation of the fee amounts and fee shares inside the `_preparePool` function of the `MainHelper` contractInteger overflow/underflow$0
- Abracadabra Money: Permanent loss of yield for stakers in reward pools due to precision loss.Integer overflow/underflow$0
- Wise Lending: Wrong use of `nftID` to check if a `PowerFarm` position is an Aave positionInteger overflow/underflow$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
- Teller Finance: `LenderCommitmentGroup_Smart` does not use `mulDiv` when converting between token and share amounts, possibly leading to DoS or loss of fundsInteger overflow/underflow$0
- Canto: Truncation exploitation of partial transfer systemInteger overflow/underflow$0
- Canto: `GaugeController::remove_gauge` will always revert whenever the gauge it's being called or has any weight attached to itInteger overflow/underflow$0
- Salty.IO: The user who withdraws liquidity from a particular pool is able to claim more rewards than they should by carefully selecting a `decreaseShareAmount` value such that the `virtualRewardsToRemove` is rounded down to zeroInteger overflow/underflow$0
- Salty.IO: Incorrect assumption in PoolMath.sol can cause underflow when zapping is usedInteger overflow/underflow$0
- Salty.IO: Suboptimal arbitrage implementationInteger overflow/underflow$0
- Flat Money Fix Review: Code asymmetry of `globalPositions.marginDepositedTotal`Integer overflow/underflow$0
- PoolTogether: `maxDeposit()` uses `yieldVault.maxDeposit()` but `_depositAndMint()` uses `yieldVault.mint()`Integer overflow/underflow$0
- PoolTogether: `PrizeVault.maxDeposit()` doesn't take into account produced feesInteger overflow/underflow$0
- Goat Trading: It's possible to create pairs that cannot be taken overInteger overflow/underflow$0
- Axis Finance: Downcasting to uint96 can cause assets to be lost for some tokensInteger overflow/underflow$0
- Axis Finance: Overflow in curate() function, results in permanently stuck fundsInteger overflow/underflow$0
- Axis Finance: Unsafe casting within _purchase function can result in overflowInteger overflow/underflow$0
- Most Aleph Zero Bridge: Most will not work with tokens with high decimals due to overflow Integer overflow/underflow$0
- Tapioca: SGL and BB repay do not round up both on allowance spending and elastic amountInteger overflow/underflow$0
- Tapioca: BBCommon::_accrue wrong value is used to prevent overflowInteger overflow/underflow$0
- Tapioca: Underflow Vulnerability in `Market::_allowedBorrow` Function: Oversight with Pearlmit Allowance HandlingInteger overflow/underflow$0
- zkSync: Reduction gate in binop operation is unsafeInteger overflow/underflow$0
- zkSync: Operator can steal all gas provided by ANY user for `L1→L2` transactionsInteger overflow/underflow$0
- zkSync: Missing range constraint on remainder check in `div` opcode implementationInteger overflow/underflow$0
- Ethereum Credit Guild: Rounding errors can cause ERC20RebaseDistributor transfers and mints to fail for underflowInteger overflow/underflow$0
- Ethereum Credit Guild: Over 90% of the Guild staked in a gauge can be unstaked, despite the gauge utilizing its full debt allocationInteger overflow/underflow$0
- Ethereum Credit Guild: `totalBorrowedCredit` can revert, breaking gauges.Integer overflow/underflow$0
- Arcadia: Stargate `STG` rewards are accounted incorrectly by `StakedStargateAM.sol`Integer overflow/underflow$0
- Collective: Malicious delegatees can block delegators from redelegating and from sending their NFTsInteger overflow/underflow$0
- Collective: ERC20TokenEmitter will not work after a certain period of timeInteger overflow/underflow$0
- Canto: secRewardsPerShare Insufficient precisionInteger overflow/underflow$0
- Canto: Loss of precission when calculating the accumulated CANTO per shareInteger overflow/underflow$0
- Olas: Withdrawals can be frozen by creating null depositsInteger overflow/underflow$0
- Flat Money: Vault Inflation AttackInteger overflow/underflow$0
- Particle Protocol: Underflow could happened when calculating Uniswap V3 position's fee growth and can cause operations to revertInteger overflow/underflow$0
- Particle Protocol: Impossible to open a position with a large `marginTo`Integer overflow/underflow$0
- JOJO Exchange Update: FundingRateArbitrage contract can be drained due to rounding errorInteger overflow/underflow$0
- JOJO Exchange Update: FundRateArbitrage is vulnerable to inflation attacksInteger overflow/underflow$0
- NextGen: Multiple mints can brick any form of `salesOption` 3 mintingsInteger overflow/underflow$0
- NextGen: `getPrice` `salesOption` 2 can round down to the lower barrier, skipping the last time periodInteger overflow/underflow$0
- Open Dollar: Incorrect calculations for Surplus Auction creation cause massive surplus imbalancesInteger overflow/underflow$0
- Wildcat Protocol: Calculation for lender withdrawals in `_applyWithdrawalBatchPayment()` should not round upInteger overflow/underflow$0
- Tapioca DAO: Overflow risk in Market contractInteger overflow/underflow$0
- Tapioca DAO: Incorrect solvency check because it multiplies collateralizationRate by share not amount when calculating liquidation thresholdInteger overflow/underflow$0
- Tapioca DAO: Incorrect formula used in function `Market.computeClosingFactor()`Integer overflow/underflow$0
- Centrifuge: Investors claiming their `maxDeposit` by using the `LiquidityPool.deposit()` will cause other users to be unable to claim their `maxDeposit`/`maxMint`Integer overflow/underflow$0
- Maia DAO Ecosystem: Maia Governance token balance dilution in `vMaia` vault is breaking the conversion rate mechanismInteger overflow/underflow$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: `UlyssesToken` asset ID accounting errorInteger 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
- Maia DAO Ecosystem: DoS of `RootBridgeAgent` due to missing negation of return values for `UniswapV3Pool.swap()`Integer overflow/underflow$0
- Maia DAO Ecosystem: `vMaia` Lacks of override in `forfeitBoost`Integer overflow/underflow$0
- Maia DAO Ecosystem: An attacker can exploit the "deposit" to drain the `Ulysess Liquidity Pool`Integer overflow/underflow$0
- Lybra Finance: Liquidation won't work when bad and safe collateral ratio are set to default valuesInteger overflow/underflow$0
- Asymmetry Finance: An attacker can manipulate the preDepositvePrice to steal from other usersInteger overflow/underflow$0