HB Token Exploit Analysis: ~$193K Lost to AMM Reserve Manipulation via Reward Path
On April 7, 2026, HB Token on BSC was exploited for ~$193,936 USDT. The attacker leveraged a structural flaw in the protocol's reward distribution mechanism — tightly coupled with live AMM reserve mutations — to distort internal spot pricing and drain the pool.
ExVul Security Team
Security Research
Event Overview
| Field | Details |
|---|---|
| Attack Time | April 7, 2026, 14:13:21 UTC |
| Transaction | 0x19671f5781acc3f5e3a869491a880aa9ee894911f4898a43254fa942d71594ed |
| Network | BSC Mainnet |
| Target | HB Token (0x5b41af6a9b314ef4d92f6809087740a83d20570a) |
| Loss | ~193,936 USDT |
| Type | Reward Accounting / AMM Reserve Manipulation |
Introduction
On April 7, 2026, HB Token on BSC was exploited for roughly $193K USDT. The root cause was a structural flaw in the protocol's reward distribution mechanism. By tightly coupling the reward claim process with live AMM reserve mutations (pair.sync()), the attacker was able to artificially distort the internal spot price and drain the pool.
How the Reward Path Worked
HB Token included a reward proxy (0xcc9d…fdb5) that handled user reward claims through a multi-step process:
- Step 1 — User initiates claimReward() call
- Step 2 — Protocol computes claimable reward amount
- Step 3 — swapBack() is called, moving HB tokens from the LP to the token contract
- Step 4 — pair.sync() is called, committing the new reserve state on-chain
- Step 5 — Reward tokens are transferred to the user and pool state is updated
Steps 2–5 all execute within the same transaction, after the user has already been identified but before the reward amount is finalized. This creates a window for reserve manipulation.
The Attack
Step 1: Flash Loan & Borrow
The attack began with a 405,231.89 WBNB flash loan from Moolah, collateralized on Venus to borrow 100,000,000 USDT.
Step 2: Pool Manipulation via Large Swap
Using the borrowed USDT, the attacker executed a large swap through PancakeSwap Router:
| Parameter | Value |
|---|---|
| Input | 72,117,360.53 USDT |
| Output | 73,608,753.06 HB |
| Post-swap USDT Reserve | 72,312,818.45 |
| Post-swap HB Reserve | 200,000.002 |
The pool was now in an extreme state — heavily USDT-weighted with minimal HB remaining.
Step 3: Trigger claimReward()
The attacker called claimReward() through a helper contract. The reward path executed, including the critical swapBack + sync sequence:
function claimReward(address user) external { uint256 reward = _computeClaimable(user); // 612.83 HB // Critical: swapBack mutates LP before reward delivery _swapBackDuringClaim(reward); // Removes ~200,000 HB from LP HB.transfer(user, reward); // User receives reward updatePool(); // Reads manipulated spot price}swapBack transferred 200,000 HB from the LP to the token contract, then called sync(). The resulting reserves became:
| Reserve | Amount |
|---|---|
| USDT | 72,312,818.45 |
| HB | 0.002 |
Step 4: Price Distortion & Extraction
With the LP now holding virtually 0 HB, the protocol's internal price query returned:
getSwapValueUSDT(1 HB) = 72,168,120.47 USDT// ~27 billion % deviation from pre-attack price of 0.0026 USDT/HBThe attacker then executed 25 direct swap rounds against the LP, using the claimed HB to extract USDT at the distorted rate, totaling 189,387,742.26 USDT in extraction.
Financial Summary
| Flow | Amount (USDT) |
|---|---|
| Initial pool buy | 72,117,360.53 |
| 25-round swap inputs | 117,076,444.73 |
| 25-round swap outputs | 189,387,742.26 |
| Net profit | 193,936.99 |
Root Cause Analysis
Three critical design flaws enabled the exploit:
- Tight Coupling of Reward Distribution and LP Operations — The reward path performed live LP mutations (swapBack + sync) before completing the claim, allowing an attacker to precondition the pool.
- Spot Price Consumption Without Sanity Checks — The protocol read getSwapValueUSDT(1 HB) directly from LP reserves without any reserve deviation checks or TWAP validation.
- No Access Control on Reserve-Critical Operations — swapBack and sync calls were reachable through the public claimReward entry point, requiring no privileged access.
function claimReward(address user) external returns (uint256) { uint256 reward = _computeClaimable(user); // Problem: LP mutation happens before reward delivery uint256 cap = HB.contractAmount(); // 200,000 HB uint256 buffered = HB.balanceOf(address(this)); HB.swapBack(cap + buffered); // Drains LP PAIR.sync(); // Commits distortion HB.transfer(user, reward); // 612.83 HB // Problem: Price read after manipulation updatePool(HB.getSwapValueUSDT(1 ether)); // 72M USDT/HB}Mitigation
Protocols must decouple reward claims from LP operations. Reward distribution should use dedicated inventory, not live AMM manipulation:
function claimReward(address user) external { uint256 reward = _computeClaimable(user); _markClaimed(user, reward); rewardToken.safeTransfer(user, reward); // From treasury, not LP}Recommendations
Decouple Reward Distribution from LP Operations
Never mutate AMM reserves (swapBack, sync) in the same execution path as reward claims. Use a separate treasury or vesting contract for reward distribution.
Use TWAP or External Oracles for Pricing
Replace raw AMM spot pricing with time-weighted average prices (TWAP) or robust external oracles like Chainlink to prevent single-block price manipulation.
Implement Reserve Deviation Guards
Add sanity checks that revert transactions when reserve ratios deviate beyond acceptable thresholds from historical averages.
Restrict Access to Reserve-Mutating Functions
Ensure functions like swapBack and sync are not reachable through unprivileged public entry points without proper access control.
Conclusion
The HB Token exploit highlights a critical anti-pattern: reading manipulated spot prices during a state-mutating transaction. To prevent this, protocols must separate reward distribution from live liquidity operations, and replace raw AMM spot pricing with TWAP or robust external oracles.
References
- Attack transaction: https://bscscan.com/tx/0x19671f5781acc3f5e3a869491a880aa9ee894911f4898a43254fa942d71594ed
- Trace analysis: https://app.blocksec.com/phalcon/explorer/tx/bsc/0x19671f5781acc3f5e3a869491a880aa9ee894911f4898a43254fa942d71594ed
- Victim contracts: HB Token (0x5b41af6a9b314ef4d92f6809087740a83d20570a), Reward Proxy (0xcc9dadc6c290f9e12a9805a005aaf3c37f46fdb5), HB (0x86ddbfc6f2e3cf096e80ca79e46042392bd90aef)
- LP Pair: Cake-LP HB/USDT (0x67a63609cf1c317196724666cc39b2da63545a96)