PoolTogether — disclosed vulnerability reports and payouts
Every publicly disclosed and closed bug bounty report we hold for PoolTogether, with our own summary of each finding and a link to the original disclosure.
- Reports indexed
- 34
- Total paid
- $0
- Critical
- 0
- Largest payout
- $0
This page collects the 34 closed, publicly disclosed PoolTogether reports indexed on CoinBuggie. Nothing here is active or unpatched — every entry was published by the programme or the researcher after remediation.
The findings concentrate in Reentrancy, Logic error, Access control, Flash loan attack, Front-running / MEV, across EVM-Solidity, Move. Reading a single protocol end to end is the fastest way to see which assumptions its codebase repeatedly gets wrong, which is usually a better predictor of where the next finding lives than the category alone.
Use the vulnerability class links below to compare these findings against the same bug class in other protocols.
What reviewers look for
- Reentrancy findings disclosed against PoolTogether
- Logic error findings disclosed against PoolTogether
- Access control findings disclosed against PoolTogether
- Flash loan attack findings disclosed against PoolTogether
- Front-running / MEV findings disclosed against PoolTogether
Curated highlights
The largest disclosed payouts in this group, with our own summary of each. Every report links back to the original disclosure.
PoolTogether: Unintended or malicious use of prize winners' hooks
In PoolTogether v5, the Vault contract allows prize winners to configure arbitrary hooks via the setHooks function. During the prize claiming process, the contract executes these user-defined hooks prior to and after prize distribution. Because the hook calls lack gas consumption caps and state-change restrictions, a user can configure a malicious hook that conducts unconstrained external operations, griefs claimers paying for transaction gas, or causes claiming transactions to revert. This results in potential gas exhaustion and denial of service for third-party prize claimers.
PoolTogether: The tier odds in `TieredLiquidityDistributor` are incorrect
The TieredLiquidityDistributor contract uses incorrect precomputed probability constants, causing the prize distribution system to deviate from its intended logic. Specifically, the highest standard prize tier should have odds of 1, mirroring the canary tier, but the generation script fails to assign this value. This configuration error means the protocol distributes prizes with incorrect frequencies, directly contradicting the project's documentation.
PoolTogether: If the underlying asset is a fee on transfer token, it could break the internal accounting of the vault
The PoolTogether vault incorrectly calculates the number of shares to mint when receiving fee-on-transfer tokens. Because the vault trusts the input amount rather than measuring the actual change in its asset balance, it mints shares based on an inflated value that does not match the actual assets received. This accounting error leads to a systemic deficit in the vault's holdings, eventually causing subsequent withdrawal attempts to revert as the contract runs out of assets to distribute to users.
PoolTogether: The threshold check for adding of new tiers is skipped when `_nextNumberOfTiers` is at the maximum amount
The PoolTogether PrizePool contract contained a logic error where tier expansion bypasses necessary validation checks. Specifically, when the protocol reached 14 tiers, a canary claim would trigger a calculation that reaches the maximum tier limit, causing the function to exit prematurely. This early return inadvertently skipped mandatory checks that ensure sufficient claim counts are met before adding a new tier, allowing the system to expand to 15 tiers regardless of actual prize pool activity levels.
PoolTogether: `TwabLib::getTwabBetween` can return inaccurate balances if `_startTime` and `_endTime` aren't safely bound
A logic issue in PoolTogether's PrizePool contract allows TWAB balance queries to occur over unsafe time ranges. When PrizePool calculates user balances via _getVaultUserBalanceAndTotalSupplyTwab, it fails to execute the required isTimeRangeSafe check before invoking TwabLib::getTwabBetween. As a result, historical balance calculations can be extrapolated incorrectly, leading to inaccurate TWAB values and potentially enabling improper prize distributions.
PoolTogether: `drawManager` can be set to a malicious address
The PoolTogether PrizePool contract is vulnerable to a front-running attack due to a missing access control modifier on the setDrawManager function. A malicious actor can intercept the initial setup to designate an attacker-controlled address as the draw manager. Because the contract prevents subsequent changes to the draw manager once assigned, this compromise is permanent, granting the attacker perpetual control over critical administrative functions, including the ability to withdraw from the reserve and manipulate prize draw operations.
All reports in this group
- PoolTogether: Vault contribution calculations wrongly include the current round when claiming prizesLogic error$0
- PoolTogether: Balance invariant between the individual and total `twabs` can be brokenLogic error$0
- PoolTogether: `depositWithPermit` and `mintWithPermit` are allowed to be called by the permit creator onlyLogic error$0
- PoolTogether: Tiers can be maintained active to give unfair advantage to user through DoSLogic error$0
- PoolTogether: `_requireVaultCollateralized()` is called at the beginning of the functions `mintYieldFee()` and `liquidate()`Logic error$0
- PoolTogether: A malicious user can steal other user's deposits from Vault.solFlash loan attack$0
- PoolTogether: Improper handling of cases when withdrawable assets = 0Logic error$0
- PoolTogether: `Vault` is not compatible with some ERC4626 vaultsLogic error$0
- PoolTogether: Increasing reserves breaks PrizePool accountingFront-running / MEV$0
- PoolTogether: `Vault.mintYieldFee` function can be called by anyone to mint `Vault Shares` to any recipient addressAccess control$0
- PoolTogether: Resetting delegation will result in user funds being lost foreverLogic error$0
- PoolTogether: `VaultFactory` allows deployment of vaults with non-authentic `TwabController` and `PrizePool`Logic error$0
- PoolTogether: Silent overflow could alter computation when calculating the `vaultPortion` in the `PrizePool` contractInteger overflow/underflow$0
- PoolTogether: Number of prize tiers always increases if just 1 canary prize is claimedLogic error$0
- PoolTogether: `Vault.mintWithPermit()` can be DoS'dFront-running / MEV$0
- PoolTogether: Vault does not conform to ERC4626Logic error$0
- PoolTogether: Delegated amounts can be forcefully removed from anyone in the `TwabController`Logic error$0
- PoolTogether: `Claimer.claimPrizes` can be front-runned in order to make losses for the claim botFront-running / MEV$0
- PoolTogether: Loss of precision leads to under-collateralizedInteger overflow/underflow$0
- PoolTogether: `maxDeposit()` uses `yieldVault.maxDeposit()` but `_depositAndMint()` uses `yieldVault.mint()`Integer overflow/underflow$0
- PoolTogether: Permit doesn't work with DAILogic error$0
- PoolTogether: `yieldFeeBalance` wouldn't be claimed after calling `transferTokensOut()`Oracle manipulation$0
- PoolTogether: Any fee claim lesser than the total `yieldFeeBalance` as unit of shares is lost and locked in the `PrizeVault` contractLogic error$0
- PoolTogether: `_maxYieldVaultWithdraw()` uses `yieldVault.convertToAssets()`Logic error$0
- PoolTogether: The winner can steal claimer fees, and force him to pay for the gasReentrancy$0
- PoolTogether: Lack of Slippage Protection in `withdraw`/`redeem` Functions of the VaultLogic error$0
- PoolTogether: `PrizeVault.maxDeposit()` doesn't take into account produced feesInteger overflow/underflow$0
- PoolTogether: Funds locked due to missing transfer checkLogic error$0