# White Eagle withdraw drain via spot-price-based WEGL payout

On 2026-05-07 08:14:47 UTC, the White Eagle withdrawal contract on BNB Chain was exploited through a spot-price manipulation logic flaw in its withdrawal path. The attacker used an orchestrator plus 11 helper contracts to call `withdraw()` repeatedly, then sold each WEGL payout into the WEGL/USDT PancakeSwap pool before the next withdrawal repriced the same USD-denominated balance into even more WEGL. The withdrawal contract lost `9888.680557825521425533 WEGL`, while the profit receiver collected `65645.944170470965224333 USDT`. In short, the contract converted internal USD balances into WEGL using a live AMM quote, so each same-transaction dump made subsequent withdrawals overpay in WEGL.

## Root Cause

### Vulnerable Contract

White Eagle withdrawal contract at `0x0079517e4157f95cefda99d295fd74fc9b9896eb` on BNB Chain. It is not a proxy per the planner stage. Source type: verified at `artifacts/analysis_0x538c8964c841369bee9fd52d3ad87de9202fd182caaa32acf58095d02f6b359d/0x0079517e4157f95cefda99d295fd74fc9b9896eb/weglcontract.sol`.

### Vulnerable Function

`withdraw()` ( `0x3ccfd60b`) in `weglcontract.sol`, with pricing delegated to `getWeglAmountFromUsd(uint256)`.

### Vulnerable Code

“`
function withdraw() public nonReentrant { User storage user = users[msg.sender]; require(user.isExist, “User not exist”); uint256 roiPending = _calculatePendingROI(msg.sender); uint256 levelPending = _calculatePendingLevelIncome(msg.sender); uint256 uplinePending = _calculatePendingUplineIncome(msg.sender); if (roiPending > 0) { user.earnedFromRoi += roiPending; _distributeRoiToInvestments(msg.sender, user); } if (levelPending > 0) { user.earnedFromLevel += levelPending; user.accumulatedLevelIncome = 0; emit LevelIncome(msg.sender, levelPending); } if (uplinePending > 0) { user.earnedFromUpline += uplinePending; emit UplineIncome(msg.sender, uplinePending); } user.lastLevelWithdraw = block.timestamp; user.lastUplineWithdraw = block.timestamp; _creditIncome(user, roiPending + levelPending + uplinePending); uint256 payoutUSD = user.availableWalletUSD; require(payoutUSD > 0, “No funds”); user.availableWalletUSD = 0; uint256 totalWegl = getWeglAmountFromUsd(payoutUSD); // <– VULNERABILITY require(weglToken.balanceOf(address(this)) >= totalWegl, “Contract Low Bal”); uint256 burnAmount = (totalWegl * 5) / 100; uint256 userAmount = totalWegl – burnAmount; if (msg.sender == COMPANY_ID) { // … } else { _safeTransfer(weglToken, msg.sender, userAmount); } emit Withdraw(msg.sender, userAmount, payoutUSD); } function getWeglAmountFromUsd(uint256 _usdAmount) public view returns (uint256) { address[] memory path = new address[](2); path[0] = address(usdtToken); path[1] = address(weglToken); return pancakeRouter.getAmountsOut(_usdAmount, path)[1]; // <– VULNERABILITY }
“`

### Why It’s Vulnerable

**Expected behavior:** a withdrawal contract that tracks balances internally in USD should redeem WEGL using a stable conversion source, a stored exchange rate, or a mechanism that cannot be worsened by the same withdrawal sequence. One withdrawal should not make the next user with the same USD balance receive more WEGL just because the previous recipient dumped into the same AMM pool.

**Actual behavior:** `withdraw()` zeroes `availableWalletUSD`, then converts that USD amount to WEGL through PancakeSwap router `getAmountsOut()` on the live WEGL/USDT pool. The trace shows each helper immediately selling its received WEGL into the same pool, so the spot quote observed by the next `withdraw()` returns a larger WEGL amount for the same USD-denominated balance.

This makes the primary flaw a `logic_error`, with `price_manipulation` as the secondary technique. The attack does not rely on reentrancy or missing auth in `withdraw()`; it relies on coupling payout sizing to a manipulable spot price that the attacker moves between identical withdrawal calls in the same transaction.

## Attack Execution

### High-Level Flow

1. The attacker EOA called an orchestrator contract.
2. The orchestrator invoked 11 helper contracts sequentially.
3. Each helper called the White Eagle contract’s `withdraw()` function.
4. `withdraw()` priced the helper’s USD-denominated wallet balance into WEGL using PancakeSwap’s live `getAmountsOut()` quote.
5. The withdrawal contract burned 5% of the computed WEGL and transferred the remainder to the helper.
6. The helper immediately swapped all received WEGL to USDT through PancakeSwap and sent the USDT to the attacker’s profit receiver.
7. Each sale pushed the WEGL/USDT spot price further down, so the next helper’s identical withdrawal redeemed more WEGL for its USD balance.
8. Repeating this 11 times drained `9888.680557825521425533 WEGL` from the withdrawal contract.

### Detailed Call Trace

– `0xcd935e0462c5b32ee4c11fb5e2d5179508ee5d7e` → `0xfc565edbfa06ee13edfa7b8b4677f89ab2382854` `claim()`( `0x4e71d92d`) via `CALL`.
– `0xfc565edbfa06ee13edfa7b8b4677f89ab2382854` → helper `0x5650c7a41ef11dfa30dc295fc4d857b7c9bbc87a` `Claim(bool)`( `0xe60b3625`) via `CALL`.
– helper → `0x0079517e4157f95cefda99d295fd74fc9b9896eb` `withdraw()`( `0x3ccfd60b`) via `CALL`.
– withdrawal contract → router `0x10ed43c718714eb63d5aa57b78b54704e256024e` `getAmountsOut(uint256,address[])`( `0xd06ca61f`) via `STATICCALL`.
– router → pair `0x9247a22981ad64e9bd1d8b9b303a2122cd88838c` `getReserves()`( `0x0902f1ac`) via `STATICCALL`.
– withdrawal contract → WEGL `0x5722ce859d00d6c59354c0750263180ffdc8ab7f` `balanceOf(address)`( `0x70a08231`) via `STATICCALL`.
– withdrawal contract → WEGL `burn(uint256)`( `0x42966c68`) via `CALL`.
– withdrawal contract → WEGL `transfer(address,uint256)`( `0xa9059cbb`) to helper via `CALL`.
– helper → WEGL `balanceOf(address)`( `0x70a08231`) via `CALL`.
– helper → router `swapExactTokensForTokensSupportingFeeOnTransferTokens(uint256,uint256,address[],address,uint256)`( `0x5c11d795`) via `CALL`.
– router → WEGL `transferFrom(address,address,uint256)`( `0x23b872dd`) via `CALL`.
– router → pair `getReserves()`( `0x0902f1ac`) via `STATICCALL`.
– router → pair `swap(uint256,uint256,address,bytes)`( `0x022c0d9f`) via `CALL`.
– pair → USDT `transfer(address,uint256)`( `0xa9059cbb`) to `0xa0d511169468ffb4dc986dbb7b58fb7fc190102b` via `CALL`.
– The same helper pattern repeats 10 more times through helpers `0x316350633c88caeb464911354f6431dc2948f84d`, `0x300270ee7353069b1841a5f6d676e99bbf8b9c38`, `0x4e76db7e93f4c5c52e0d6ba88c2490a49a3626a9`, `0x141379b7e1d5d272e05e00e58bf88efd1ddbdf3b`, `0x14a61089e423c3845c411fa33461fe31f90ea3e5`, `0xe1915a78ba553f310189e3071e5407a3c9288664`, `0x7c8186a60b7edcb2d6f4e29aab183f20c5267575`, `0x9e290f287f64e5fede397b1735b0e4885e5f8927`, `0xb758b842f35dc4bf9c231c36a06a1355d3779b8d`, and `0xba4d2e4300b227245701d2c5bf93948fb5c30e71`.

The recovered orchestrator confirms this batching behavior: `0xfc565edbfa06ee13edfa7b8b4677f89ab2382854/recovered.sol` hard-codes 11 helper calls, and each helper’s recovered code shows `Claim(bool)` calling `withdraw()` and then swapping WEGL to USDT for profit receiver `0xa0d511169468ffb4dc986dbb7b58fb7fc190102b`.

## Financial Impact

The primary victim was the White Eagle withdrawal contract, which lost `9888.680557825521425533 WEGL` according to `funds_flow.json`. The paired PancakeSwap pool absorbed `9188.709810105814000167 WEGL`, while `699.970747719707425366 WEGL` was burned across the withdrawal and transfer path.

The profit receiver `0xa0d511169468ffb4dc986dbb7b58fb7fc190102b` gained `65645.944170470965224333 USDT` across the 11 swaps. The largest single payout in the trace was `11719.558694305319350229 USDT`, and later payouts declined as pool state changed, which matches the attack pattern of repeatedly converting the same internal USD logic into progressively more WEGL while extracting external USDT liquidity.

Because the payout asset was the protocol’s own WEGL inventory, the exploit directly impaired the solvency of the withdrawal path. The contract’s status field in `receipt.json` is `0x1`, confirming the full drain sequence executed successfully in a single transaction.

## Evidence

– `receipt.json:1878` shows transaction status `0x1`.
– `trace_callTracer.json` shows `withdraw()`( `0x3ccfd60b`) called 11 times, each followed by a helper swap through PancakeSwap router and pair.
– `selectors.json` resolves the key selectors used in the report: `claim()`, `Claim(bool)`, `withdraw()`, `getAmountsOut(uint256,address[])`, `swapExactTokensForTokensSupportingFeeOnTransferTokens(uint256,uint256,address[],address,uint256)`, and `swap(uint256,uint256,address,bytes)`.
– `funds_flow.json` records the withdrawal contract’s net loss of `9888.680557825521425533 WEGL` and the profit receiver’s gain of `65645.944170470965224333 USDT`.
– `receipt.json` logs confirm the burn-and-transfer pattern for each withdrawal: WEGL is first burned from the withdrawal contract, then transferred to the helper, then transferred from the helper into the Pancake pair.