We do not have a reliable USD price for the recorded assets yet.
0xba0fa8c150b2408eec9bbbbfe63f9ca63e99f3ff53ac46ee08d691883ac05c1d0x1bf7fe7568211ecff68b6bc7ccad31ecd8fe8092BSC0x8f52e0c41164169818c1fb04b263fdc7c1e56088BSCOn BSC block 8589726, transaction 0xba0fa8c150b2408eec9bbbbfe63f9ca63e99f3ff53ac46ee08d691883ac05c1d used a public flash-loan path to farm xWin referral rewards with no durable capital left in the protocol at the end of each loop. The attacker borrowed 76000 BNB, primed a self-controlled referral account, executed 20 large subscribe/redeem loops against xWinDefi and xWinFarm, withdrew 303998867654180932516586 XWIN from xWinDefi, sold the reward, repaid the flash loan plus fee, and retained 842436308973088883142 wei of net BNB profit.
The root cause is a reward-accounting flaw in xWinDefi: referral rewards are credited from gross subscription volume in _updateReferralReward, but that referral-side credit is not reversed when the subscribed position is redeemed immediately. The exploit is an ACT opportunity because all required steps use public on-chain contracts and unprivileged attacker-controlled helpers.
xWinDefi at 0x1bf7fe7568211ecff68b6bc7ccad31ecd8fe8092 is the protocol entrypoint that forwards user actions into fund contracts and tracks reward state in xWinRewards. xWinFarm at 0x8f52e0c41164169818c1fb04b263fdc7c1e56088 is one such fund; on subscribe it mints fund shares and on redeem it burns those shares and returns BNB plus any converted farm proceeds to the investor.
At the exploit block, three public conditions were already in place. First, xWinDefi still treated xWinFarm as a valid fund. Second, storage slot 17 in xWinDefi contained 200000000000000000, meaning the live referral reward rate was 0.2e18, or 20% of the subscribed amount. Third, the public Bank entrypoint 0x0cea0832e9cdbb5d476040d58ea07ecfbebb7672 and BankController liquidity source 0xc78248d676debb4597e88071d3d889eca70e5469 had enough BNB liquidity to lend 76000 BNB permissionlessly.
The vulnerability is a protocol logic flaw in xWin reward accounting, not a privileged-access incident. In xWinDefi, referral rewards are based on raw subscription notional instead of retained exposure or realized revenue. The referral path only checks whether the referral helper already has nonzero accBasetoken, so a minimal priming subscription is enough to enable large downstream credits. Once the attacker begins the large loops, each Subscribe call adds referral credit proportional to the full input amount. When the newly minted xWinFarm shares are redeemed in the same transaction, the redeemer-side reward state is updated, but the referral helper's credited reward balance is left intact. That leaves permanent, withdrawable XWIN reward claims backed only by transient flash-loan volume. Because the entire path is available through public contracts, an unprivileged adversary can reproduce it deterministically.
The decisive victim-side logic sits in xWinDefi::_updateReferralReward, xWinDefi::WithdrawReward, and xWinDefi::_updateRewardBal. The verified xWinDefi source shows that referral credit is computed directly from the incoming subscription amount:
function _updateReferralReward(xWinLib.TradeParams memory _tradeParams, address _managerAddress) internal {
xWinLib.xWinReferral storage _xWinReferral = xWinReferral[msg.sender];
if(_xWinReferral.referral == address(0)){
_xWinReferral.referral = _tradeParams.referral;
}
xWinLib.xWinReward storage _xwinReward = xWinRewards[_xWinReferral.referral];
if(_xwinReward.accBasetoken > 0){
uint256 entitleAmt = _tradeParams.amount.mul(referralperunit).div(1e18);
_xwinReward.previousRealizedQty = _xwinReward.previousRealizedQty.add(entitleAmt);
}
}
The same source shows that WithdrawReward transfers the accrued quantity immediately, while the redeem-side update only touches the redeemer's own xWinRewards[from] entry:
function WithdrawReward() external nonReentrant onlyNonEmergency payable {
xWinLib.xWinReward storage _xwinReward = xWinRewards[msg.sender];
uint256 rewardQty = GetEstimateReward(msg.sender);
require(rewardQty > 0, "No reward");
_xwinReward.previousRealizedQty = 0;
_xwinReward.blockstart = block.number;
if(amountWithdraw > 0) _sendRewards(msg.sender, amountWithdraw);
}
function _updateRewardBal(address from, uint256 redeemUnit) internal returns (uint256 rewardQty){
xWinLib.xWinReward storage _xwinReward = xWinRewards[from];
...
_xwinReward.accBasetoken = _xwinReward.accBasetoken.sub(reducedBal);
_xwinReward.accMinttoken = _xwinReward.accMinttoken.sub(redeemUnit);
_xwinReward.previousRealizedQty = 0;
}
The fund-side behavior makes the round-trip possible. The collected xWinFarm source shows that Subscribe mints fund shares to the investor and refunds leftover BNB or XWIN, while Redeem burns the supplied shares and returns value back to the investor:
function Subscribe(TradeParams memory _tradeParams, address _investorAddress)
external onlyxWinProtocol payable returns (uint256)
{
...
mint(_investorAddress, liquidity);
if(_tradeParams.amount.sub(amountBNB).sub(halfAmt) > 0)
TransferHelper.safeTransferBNB(_investorAddress, _tradeParams.amount.sub(amountBNB).sub(halfAmt));
if(swapOutput.sub(amountToken) > 0)
TransferHelper.safeTransfer(farmToken, _investorAddress, swapOutput.sub(amountToken));
}
function Redeem(TradeParams memory _tradeParams, address _investorAddress)
external onlyxWinProtocol payable returns (uint256)
{
...
_burn(msg.sender, _tradeParams.amount);
...
}
This means the protocol invariant should have been: a same-transaction subscribe-and-full-redeem round-trip must not leave referral rewards behind unless durable exposure remains. Instead, the seed transaction proves the opposite. The parsed evidence shows 21 _Subscribe events, 20 _Redeem events, and a final _WithdrawReward that transferred 303998867654180932516586 XWIN. The same evidence also shows that the 20 large-loop subscriptions totaled 1519994338270904662582974 wei, which at a 20% referral rate yields 303998867654180932516594.8 before loop-level truncation, matching the on-chain withdrawn amount to normal integer-rounding tolerance.
The adversary cluster consisted of EOA 0xb63f0d8b9aa0c4e68d5630f54bfefc6cf2c2ad19, orchestrator 0x67d3737c410f4d206012cad5cb41b2e155061945, redeem helper 0x70fec992a60e1b7751c37289125ea8c6078aeda7, and referral helper 0x2df8dd8880010a28b1539d9aeff9bceec39e2040. The helper contracts were created by the attacker EOA in transaction 0xf4caf88c125fe3e48eae38e6fcdc9471c72d5bdffd4f0fb76a2dedc03259c9be.
The exploit flow was:
76000 BNB.10 wei priming subscription so its xWinRewards[referral].accBasetoken became nonzero.xWinDefi.Subscribe calls into xWinFarm, always naming the primed referral helper as the referral address.xWinFarm shares to the redeem helper, which redeemed them back through xWinDefi.Redeem.WithdrawReward, receiving 303998867654180932516586 XWIN from xWinDefi.76060.8 BNB, and kept the residual BNB profit.The seed trace records the public flash-loan and final reward withdrawal directly:
emit FlashLoan(... amount: 76000000000000000000000, fee: 60800000000000000000)
...
emit _WithdrawReward(from: 0x2Df8DD8880010A28b1539d9aEfF9bcEec39E2040, rewardQty: 303998867654180932516586)
emit Swap(... amount1In: 303998867654180932516586, amount0Out: 903920326455431480025, ...)
That trace is consistent with the balance diff, which shows xWinDefi losing the same 303998867654180932516586 XWIN and the attacker EOA gaining 842436308973088883142 wei net.
The direct protocol loss was 303998867654180932516586 XWIN withdrawn from xWinDefi reward inventory. The extracted reward was then monetized into BNB, leaving the attacker with 842436308973088883142 wei of net profit after flash-loan fees and gas. The affected public protocol components were xWinDefi as the reward-paying victim and xWinFarm as the fund used to synthesize transient subscription volume.
0xba0fa8c150b2408eec9bbbbfe63f9ca63e99f3ff53ac46ee08d691883ac05c1d on BSC block 85897260xf4caf88c125fe3e48eae38e6fcdc9471c72d5bdffd4f0fb76a2dedc03259c9bexWinDefi at 0x1bf7fe7568211ecff68b6bc7ccad31ecd8fe8092, xWinFarm at 0x8f52e0c41164169818c1fb04b263fdc7c1e560880x0cea0832e9cdbb5d476040d58ea07ecfbebb7672, BankController 0xc78248d676debb4597e88071d3d889eca70e5469artifacts/collector/seed/56/0xba0fa8c150b2408eec9bbbbfe63f9ca63e99f3ff53ac46ee08d691883ac05c1d/trace.cast.log, metadata.json, and balance_diff.jsonartifacts/auditor/iter_0/evidence_summary.txthttps://bscscan.com/address/0x1bf7fe7568211ecff68b6bc7ccad31ecd8fe8092#code