Goat Trading — disclosed vulnerability reports and payouts
Every publicly disclosed and closed bug bounty report we hold for Goat Trading, with our own summary of each finding and a link to the original disclosure.
- Reports indexed
- 4
- Total paid
- $0
- Critical
- 0
- Largest payout
- $0
This page collects the 4 closed, publicly disclosed Goat Trading reports indexed on Coin Buggie. Nothing here is active or unpatched — every entry was published by the programme or the researcher after remediation.
The findings concentrate in Logic error, Integer overflow / underflow, across EVM-Solidity. 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
- Logic error findings disclosed against Goat Trading
- Integer overflow / underflow findings disclosed against Goat Trading
Curated highlights
The largest disclosed payouts in this group, with our own summary of each. Every report links back to the original disclosure.
Goat Trading: No check for `initialEth` in `GoatV1Pair.takeOverPool()`.
GoatV1Pair.takeOverPool() allows a new team to seize control of an AMM pool after the initialLP vesting period. The takeover only validates the token amount being contributed (L481) and never checks the initialEth parameter. Because a smaller initialEth produces a larger computed token-amount requirement, a caller can set initialEth to 0 and trivially pass the token-amount gate, letting them take over the pool under conditions the original initial provider never consented to. Sherlock adjudicated it Medium and Unique, and the team fixed it by adding an initialEth check in PR inedibleX/goat-trading#6. All statements are directly from the supplied source material (issue #43 by whitehair0330 and the adjudication thread).
Goat Trading: The router is not compatible with fee on transfers tokens
Goat Trading's GoatRouterV1 assumes all ERC20s are standard and fails to account for fee-on-transfer tokens. In removeLiquidity, the router burns liquidity and sends TOKEN directly to the recipient, then enforces a token minimum that does not discount the transfer fee, so the recipient receives less than the checked amount; in removeLiquidityETH, tokens pass through the router to the recipient, incurring the fee twice. The finding was confirmed as a medium by the Sherlock judge and fixed by adding dedicated 'SupportingFeeOnTransferTokens' router functions modeled on Uniswap Router02.
Goat Trading: It's possible to create pairs that cannot be taken over
Goat Trading's pair factory (GoatV1Factory) allows createPair() to be called with unvalidated initial bootstrap parameters. An attacker can set virtualEth, bootstrapEth, initialEth, and initialTokenMatch all to type(uint112).max, which causes the internal _tokenAmountsForLiquidityBootstrap computation k = virtualEth * initialTokenMatch; tokenAmtForAmm = (k * bootstrapEth) / (totalEth * totalEth) to overflow (2^336 exceeds 2^256). This makes takeOverPool() always revert, so the pair can never be rescued and new pair creation is permanently blocked. The finding was confirmed by the protocol team and fixed in a subsequent PR that validates initial parameters and mints liquidity at pool creation.
Goat Trading: Liquidity provider fees can be stolen from any pair
Goat Trading's AMM pair has a fee-accounting flaw that lets any liquidity provider drain all currently pending LP swap fees from a pair. The bug combines two quirks: transferring LP tokens to the pair contract itself skips the fee-tracking update so the pair's accrued fee entitlement stays at zero, while withdrawFees() is permissionless and can withdraw on behalf of any address including the pair. An attacker adds liquidity, transfers those LP tokens to the pair, calls withdrawFees(address(pair)) claiming the pair's unearned fees, then burns the transferred LP tokens and swaps the excess WETH out of the pool to extract value that rightfully belongs to other LPs. The finding was upheld at High severity by Sherlock with a fix adding require(to != address(this)) to withdrawFees() and signed off by the Lead Senior Watson.