# xWin Finance: invalid slippage control enables flash-loan reward farming

xWin Finance's Subscribe/Redeem used a user-supplied priceImpactTolerance of 10000, letting an attacker flash-loan BNB, subscribe/redeem repeatedly to farm XWIN rewards, and drain ~$300k.

- Payout: Real-world hack
- Severity: high
- Program: xWin Finance
- Analysis by: DeFiHackLabs
- Disclosed: 2021-06-25
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2021-06/xWin_exp.sol
- Library page: http://bugbountylibrary.com/r/dhl%3A20210625-xwin
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:flash-loan vuln:oracle-manipulation vuln:reward-distribution

**Target:** BSC DeFi Subscribe/Redeem reward contract and PCLPXWIN/XWIN PancakeSwap pairs
**Root cause:** Subscribe/Redeem accepted a caller-supplied priceImpactTolerance (set to 10000 = 100%) with no validation, so trades executed at any price while still accruing subscription rewards.
**Steps:**
1. Flash-loan 76,000 BNB from bank `0x0cEA0832e9cdBb5D476040D58Ea07ecfbeBB7672`.
2. Deploy SimpleAccount, fund with 11 wei, call `Subscribe` with `priceImpactTolerance: 10_000` to register a referral.
3. Loop 20x: call `xWinDefi.Subscribe{value: bnbbalance}(tradeParams)` with `priceImpactTolerance: 10_000` and `referral: account1`.
4. Swap received XWIN into WBNB via `xwinwbnbpair.swap(wbnbout,0,...)` after `XWIN.transfer` to the pair.
5. Call `redeem()` approving PCLPXWIN and `xWinDefi.Redeem(tradeParams)` with `priceImpactTolerance: 10_000`.
6. Call `account1.withdrawRewards()` to collect XWIN rewards.
7. Dump remaining XWIN on `xwinwbnbpair2`, withdraw WBNB, repay flash loan + fee.
**How found:** PeckShield root-cause analysis identified that the protocol trusted the user-supplied `priceImpactTolerance` field, allowing trades at any slippage while rewards still accrued.
**Exploitation:** Attacker flash-borrowed 76k BNB, registered a referral account, then repeatedly subscribed with a 100% price-impact tolerance so the protocol accepted arbitrarily bad swap prices while still paying subscription incentives. Each iteration converted accrued XWIN back to WBNB on PancakeSwap, redeemed PCLPXWIN, and looped 20 times; referral rewards were withdrawn and remaining XWIN dumped on a second pair before repaying the loan.
**Escalation:** Referral account plus 20-iteration loop compounded reward accrual on top of the flash-loaned principal.
**Insight:** When a DeFi protocol takes a slippage/price-impact parameter from the caller, check whether rewards or accounting are computed independently of realized execution price — a maxed-out tolerance plus a flash loan turns reward accrual into free money.

## Proof of concept (copied exactly from the original report)

**Redeem with max priceImpactTolerance**

```
function redeem() public payable {
        PCLPXWIN.approve(
            address(xWinDefi), 1_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000
        );
        uint256 pclpxwinbalance = PCLPXWIN.balanceOf(address(this));
        TradeParams memory tradeParams = TradeParams({
            xFundAddress: address(PCLPXWIN),
            amount: pclpxwinbalance,
            priceImpactTolerance: 10_000,
            deadline: 10_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000,
            returnInBase: false,
            referral: 0x0000000000000000000000000000000000000000
        });
        xWinDefi.Redeem(tradeParams);
    }
```

