This is a lower bound: only assets with reliable historical USD prices are counted, so the actual loss may be higher.
0x31262f15a5b82999bf8d9d0f7e58dcb1656108e6031a2797b612216a95e1670e0xa79fe386b88fbee6e492eeb76ec48517d1ec759aBSCOn BNB Smart Chain block 9728756, an unprivileged attacker exploited Wault Finance's WUSD Master at 0xa79fe386b88fbee6e492eeb76ec48517d1ec759a in transaction 0x31262f15a5b82999bf8d9d0f7e58dcb1656108e6031a2797b612216a95e1670e. The attacker flash-borrowed WUSD, redeemed it against WUSD Master's pooled reserves, manipulated the live WEX/USDT WaultSwap price upward with flash-borrowed USDT, called stake(250000 ether) 68 times to mint 17,000,000 new WUSD at the distorted price, repaid the flash swaps, and finished with 370.191870506716646228 Binance-Peg ETH profit.
The root cause is that WUSD Master minted fixed nominal WUSD against a same-transaction, manipulable AMM spot swap while redeem(uint256) let every WUSD holder claim a pro-rata share of the contract's entire WEX reserve. That combination let the attacker add underpriced backing during stake, immediately convert the newly minted WUSD into claims on historical WEX reserves, and extract value from the victim contract.
WUSD Master accepted USDT deposits through stake(uint256). The verified source on BscScan shows that the function transferred the user's USDT into the contract, computed wexAmount = amount * wexPermille / 1000, approved the router, executed swapExactTokensForTokensSupportingFeeOnTransferTokens(wexAmount, 0, swapPath, address(this), block.timestamp), and then minted amount WUSD to the caller. The mint amount therefore tracked the nominal USDT deposit, not the market value of the WEX actually obtained.
WUSD Master also exposed redeem(uint256). That function computed the caller's USDT share and a WEX share using wex.balanceOf(address(this)) * amount / wusd.totalSupply(), burned the caller's WUSD, then transferred both USDT and WEX out of the victim contract. Every newly minted WUSD therefore immediately participated in the entire pooled WEX reserve.
The relevant public liquidity venues were the WUSD/BUSD WaultSwap pair at 0x6102d8a7c963f78d46a35a6218b0db4845d1612f, the WEX/USDT WaultSwap pair at 0x50e8d9aa83ebde9608074ec1faadfd2e792d9b81, and the Pancake USDT/WBNB pair at 0x16b9a82891338f9ba80e2d6970fdda79d1eb0dae. The exploit depended only on public pools, flash liquidity, and publicly callable victim functions.
This was an ATTACK-class ACT price-manipulation exploit against protocol accounting, not an access-control failure. The critical design error is that WUSD Master treated a same-transaction AMM swap as a trustworthy pricing mechanism for the WEX backing leg, while minting WUSD equal to the full nominal USDT deposit regardless of how little WEX the manipulated swap returned. The contract also set amountOutMin = 0, removing any protection against severe price impact during accounting-critical swaps. Because redeem(uint256) distributed WEX pro-rata across total WUSD supply, the attacker could mint fresh WUSD after pushing WEX/USDT off fair price and then redeem or settle those units against previously accumulated WEX reserves already sitting in WUSD Master. The invariant that one unit of newly minted WUSD should correspond to honestly measured backing therefore failed at the code path where stake(uint256) called the router and then unconditionally executed wusd.mint(msg.sender, amount). The exploit is completed by redeem(uint256), where wexTransferAmount is computed from the full contract WEX balance and total supply instead of from the marginal value just contributed by the new minter.
The verified WUSD Master source contains the exploit-enabling logic directly:
function stake(uint256 amount) external nonReentrant {
require(amount <= maxStakeAmount, "amount too high");
usdt.safeTransferFrom(msg.sender, address(this), amount);
uint256 wexAmount = amount * wexPermille / 1000;
usdt.approve(address(wswapRouter), wexAmount);
wswapRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
wexAmount,
0,
swapPath,
address(this),
block.timestamp
);
wusd.mint(msg.sender, amount);
}
function redeem(uint256 amount) external nonReentrant {
uint256 wexTransferAmount = wex.balanceOf(address(this)) * amount / wusd.totalSupply();
wusd.burn(msg.sender, amount);
wex.safeTransfer(msg.sender, wexTransferAmount);
}
The first half of the exploit used WUSD Master's redeem path to extract existing reserves before the manipulated minting phase. In the reproduced forge execution log, WUSD Master redeemed 16839004009795998331120773 WUSD and transferred both 15037230580747826509690850 USDT and 106502606009336810473769680 WEX to the attacker test contract. The collector balance diff independently confirms large negative deltas at WUSD Master and matching positive deltas for the public pools that absorbed the unwind.
The second half used public liquidity to distort the WEX/USDT spot price inside the same transaction. The transaction trace shows a nested flash borrow of USDT from the Pancake USDT/WBNB pair and then a Wault router swap into the WEX/USDT pair before the staking loop. After that manipulation, each stake(250000 ether) call still minted 250,000 WUSD even though the WEX leg of the backing purchase had become much worse. The reproduced validator forge log shows a manipulated stake routing 25,000 USDT into the WEX/USDT pair and receiving roughly 100,557.804540898830745403 WEX at the distorted price before wusd.mint still minted the full 250000000000000000000000 WUSD.
That mismatch is the invariant violation. The victim contract measured the WEX leg with a price the attacker had just manipulated upward, but it minted WUSD against the nominal deposit amount and then let those newly minted units claim from the contract's entire WEX inventory. Repeating that cycle 68 times minted 17,000,000 WUSD under distorted pricing. Both the seed artifacts and the validator PoC execution confirm that the newly minted supply is large enough to repay the borrowed WUSD and still leave a meaningful residual profit after repaying the USDT flash swap.
The attack remained permissionless end to end. The collector metadata shows the exploit transaction originated from EOA 0x886358f9296de461d12e791bc9ef6f5a03410c64, deployed helper contract 0x50afa9383ea476bdf626d6fba62afd0b01c8fea1, and used only public AMMs, router calls, and WUSD Master entrypoints. No privileged keys, governance actions, or attacker-exclusive contracts were required beyond the attacker's freshly deployed helper contract.
The adversary's execution path was a single crafted transaction with nested flash liquidity.
First, the attacker borrowed 16,839,004.009795998331120773 WUSD from the WUSD/BUSD WaultSwap pair. The callback immediately approved WUSD Master and redeemed the borrowed WUSD through the victim contract. The forge execution log records:
WUSD Master::redeem(16839004009795998331120773)
emit Transfer(... param1: PoC Attacker, param2: 15037230580747826509690850)
emit Transfer(... param1: PoC Attacker, param2: 106502606009336810473769680)
Second, inside the same outer callback, the attacker borrowed USDT from the Pancake USDT/WBNB pair and used a large portion of it to buy WEX aggressively from the WEX/USDT pair. The seed trace and the reproduced PoC both show the router calling the WEX/USDT pair immediately before the manipulated staking loop.
Third, the attacker repeatedly called stake(250000 ether) 68 times. The validator forge log shows the exact victim-side mechanics for an iteration:
WUSD Master::stake(250000000000000000000000)
USDT::transferFrom(PoC Attacker, WUSD Master, 250000000000000000000000)
Wault Router::swapExactTokensForTokensSupportingFeeOnTransferTokens(
25000000000000000000000,
0,
[USDT, WEX],
WUSD Master,
1628041741
)
WEX/USDT Pair::swap(0, 100557804540898830745403, WUSD Master, 0x)
Fourth, after minting 17,000,000 WUSD in aggregate, the attacker sold the accumulated WEX back through public liquidity, repaid the inner USDT flash swap, and then repaid the outer WUSD flash swap. The remaining value was routed through public markets until the original EOA realized a positive Binance-Peg ETH balance delta.
The measurable victim loss was the depletion of WUSD Master's redeemable backing. The root-cause artifact records two primary loss legs:
15037230580747826509690850 raw units106502606009336810473769680 raw unitsThe collector balance diff confirms that the attacker EOA ended with a positive 370.191870506716646228 Binance-Peg ETH delta while paying 0.104896728 BNB in gas. The exploit also caused severe same-transaction dislocations across the WEX/USDT, WUSD/BUSD, USDT/WBNB, and downstream settlement pools that absorbed the unwind.
0x31262f15a5b82999bf8d9d0f7e58dcb1656108e6031a2797b612216a95e1670ehttps://bscscan.com/address/0xa79fe386b88fbee6e492eeb76ec48517d1ec759a#code/workspace/session/artifacts/collector/seed/56/0x31262f15a5b82999bf8d9d0f7e58dcb1656108e6031a2797b612216a95e1670e/metadata.json/workspace/session/artifacts/collector/seed/56/0x31262f15a5b82999bf8d9d0f7e58dcb1656108e6031a2797b612216a95e1670e/trace.cast.log/workspace/session/artifacts/collector/seed/56/0x31262f15a5b82999bf8d9d0f7e58dcb1656108e6031a2797b612216a95e1670e/balance_diff.json/workspace/session/artifacts/validator/forge-test.log