Skip to content

Add PoC: FoxLpBondsPool stale _stakeAmount from manipulable AMM spot quote (~112,976 USDC, Aug 2026) - #1209

Merged
SunWeb3Sec merged 2 commits into
SunWeb3Sec:mainfrom
BhariGowda:feat/foxlpbonds-2026-08
Aug 18, 2026
Merged

Add PoC: FoxLpBondsPool stale _stakeAmount from manipulable AMM spot quote (~112,976 USDC, Aug 2026)#1209
SunWeb3Sec merged 2 commits into
SunWeb3Sec:mainfrom
BhariGowda:feat/foxlpbonds-2026-08

Conversation

@BhariGowda

Copy link
Copy Markdown
Contributor

Stale _stakeAmount from manipulable AMM spot quote (~112,976.12 USDC, ~$118.7K reported, BSC)

Root cause, confirmed against the trace: FoxLpBondsPool.stake() calculates and fixes a _stakeAmount value from a manipulable Pancake AMM spot quote BEFORE executing its own large USDT->Fox swap. That swap materially skews the pair's reserves. The subsequent addLiquidity() call then supplies Fox and USDT according to the now-different reserve ratio, but _stakeAmount is never recomputed from the actual assets deposited or the fair value of the resulting LP tokens.

Treasury.lpBonds() trusts this stale, economically unsupported _stakeAmount, mints Fox based on it, and immediately transfers an inviter referral reward to an attacker-controlled address in the same flow. The attacker then sells the newly-minted Fox back into the pair in the same transaction. Flash-loan liquidity (multi-pool USDT aggregation, ~482M USDT, fully repaid at tx end) funds the scale of the swap the core vulnerability is the lack of manipulation-resistant pricing, no accounting-to-actual-backing validation, and immediate (non-delayed) reward settlement.

Every step (flash loan, USDT->Fox swap, stake(), addLiquidity(), referral reward transfer, sell-back) is a plain permissionless call chain from a plain EOA. No signer, admin role, or privileged path anywhere in the trace.

Attack sequence traced:

  1. USDT->Fox swap skews the USDT/Fox pair reserves.
  2. addLiquidity() at the now-skewed ratio mints LP tokens to the pool.
  3. Treasury mints Fox off the stale _stakeAmount (pre-swap valuation).
  4. Inviter reward (Fox) sent to an attacker-controlled referral address.
  5. Minted Fox sold back into the pair for USDT.

PoC forks at block-1 (attack contracts already deployed on-chain, no same-block setup needed), calls the already-deployed attack contract with exact on-chain calldata, pranks the caller as both msg.sender and tx.origin. Asserts net attacker USDT gain: 112,976.12 USDC on-chain, close to the reported ~$118.7K (remainder is WBNB/USDC dust from the two flash-loaned LP tokens).

Attacker: 0x3a82a2a77061017927e5331fffd07c0308a1d2da (controlled by 0x5670d36f00bc7f6860b6afddb288e3668efc0ef9)
Victim (USDT/Fox PancakePair): 0xaab18bcdee287aea288c0560612caadf7c328803
FoxLpBondsPool: 0x58e2a853bb14e46befd3148bd4280370fea4655a
Treasury: 0x87614d97808dcdecb069fe8489848fa1c001e04d
Tx: https://bscscan.com/tx/0x8e1775cbfd44db29744cc6687ff1822d2c47321de6e94062f789ad6181ad5514

Run: forge test --contracts src/test/2026-08/FoxLpBondsPool_exp.sol --evm-version cancun -vvv

@SunWeb3Sec

Copy link
Copy Markdown
Owner

🤖 Automated PR review — changes requested

Thanks for the contribution! This PR can't be merged yet:

  • forge test --contracts src/test/2026-08/FoxLpBondsPool_exp.sol --evm-version cancun -vvv PASSES (BSC archive fork, no --ffi):
    [PASS] testExploit() (gas: 4787900)
    Logs:
      attacker USDT gain: 112976.118753142627232237
      attacker FOX balance: 0.000000000000000000
    
  • ✅ README count bumped correctly: 853854.
  • ✅ New entry is in the correct newest-first chronological position in both the TOC and the detail list.
  • ❌ The new TOC anchor doesn't resolve to its detail header — it's missing the underscore from _stakeAmount:
    • TOC link points to: #20260815-foxlpbondspool---stale-stakeamount-from-manipulable-amm-spot-quote
    • Detail header ### 20260815 FoxLpBondsPool - Stale _stakeAmount from manipulable AMM spot quote actually slugs to: #20260815-foxlpbondspool---stale-_stakeamount-from-manipulable-amm-spot-quote

Please fix the TOC link (add the missing _ before stakeamount) and push an update — the reviewer will re-run automatically.

@SunWeb3Sec
SunWeb3Sec merged commit 04a31c7 into SunWeb3Sec:main Aug 18, 2026
@SunWeb3Sec

Copy link
Copy Markdown
Owner

🤖 Automated PR review — merged ✅

  • 🧪 forge test --contracts src/test/2026-08/FoxLpBondsPool_exp.sol --evm-version cancun: PASS (attacker USDT gain: 112,976.12)
  • 📄 README: count 853→854, TOC anchor now resolves correctly after the fix

Thanks for the contribution and for the quick anchor fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants