# PegaBall: buyGamesFrom self-funds tickets, vendor drains proxy

PegaBall's buyGamesFrom self-funded purchases via payable(this).call instead of requiring msg.value, letting a vendor drain proxy ETH via repeated calls.

- Payout: Real-world hack
- Severity: high
- Program: PegaBall
- Credited: DeFiHackLabs
- Disclosed: 2025-06-03
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2025-06/PegaBall_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20250603-pegaball
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity vuln:business-logic

**Target:** PegaBall proxy contract (buyGamesFrom, vendorRegistration)
**Root cause:** buyGamesFrom checked the buyer's ETH balance and self-funded the purchase via payable(this).call rather than requiring the caller to send the ticket price as msg.value.
**Steps:**
1. Flash-borrow 0.7 WETH from Uniswap V2 WETH/USDT pair via `swap(0.7 ether, 0, attackContract, abi.encode(attackContract))`.
2. In `uniswapV2Call`, unwrap WETH to ETH via `IWETH.withdraw(amount0)`.
3. Register as vendor: `pegaBall.vendorRegistration(address(this), profitReceiver)` routing payouts to attacker.
4. Loop: compute `amountFromProxyBalance = PEGA_BALL_PROXY.balance / gamePrice`; while >60, call `pegaBall.buyGamesFrom(amountFromProxyBalance - 1)` without sending msg.value.
5. Repay flash loan: `repayAmount = (amount0 * 1004) / 1000 + 1`; deposit ETH to WETH and transfer to pair.
6. Forward remaining ETH balance to profitReceiver.
**Exploitation:** Attacker flash-borrowed WETH, registered as a vendor with attacker-controlled payout, then repeatedly called buyGamesFrom without paying msg.value. The contract self-funded each purchase from its own balance via payable(this).call, and the vendor/referrer cuts were paid out to the attacker, draining the proxy's ETH. Flash loan repaid from proceeds.
**Insight:** Look for payable functions that check the caller's balance or self-fund via payable(this).call instead of requiring msg.value; vendor/referrer payout logic combined with such self-funding lets an attacker mint purchases from the contract's own balance.
