# Malicious tickets can lead to the loss of all tokens

TwabRewards accepted any contract implementing ITicket, so an attacker's fake ticket returned inflated balances and drained reward tokens from promotions.

- Payout: Audit contest
- Severity: high
- Program: PoolTogether
- Found by: johnnycash
- Disclosed: 2022-02-03
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2021-12-pooltogether-findings/issues/1
- Library page: https://bugbountylibrary.com/r/c4%3A2021-12-pooltogether%3AH-05
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** TwabRewards.createPromotion/claimRewards reward accounting
**Root cause:** _requireTicket() only checks the ticket implements the ITicket interface, so an attacker-controlled ticket can return arbitrary getAverageBalanceBetween and getAverageTotalSuppliesBetween values used directly in reward math.
**Steps:**
1. Attacker deploys EvilTicket implementing ITicket where getAverageBalanceBetween returns 1337 and getAverageTotalSuppliesBetween returns [1].
2. Call `createPromotion(evilTicket, rewardToken, tokensPerEpoch, startTime, epochDuration, 0)` — zero epochs makes it free.
3. Advance time past an epoch, then call `claimRewards(attacker, promotionId, [epochId])`.
4. _calculateRewardAmount computes tokensPerEpoch*1337/1, and safeTransfer pays the attacker from the promotion's token balance.
**How found:** Code reading of _requireTicket() showed only an interface check; tracing claimRewards into _calculateRewardAmount revealed the ticket-supplied averages feed reward math unchecked.
**Exploitation:** Attacker registers a promotion pointing at a malicious ticket and the victim promotion's reward token, then claims a single epoch; the fake ticket inflates the reward amount so the contract transfers the promotion's tokens to the attacker at no cost.
**Escalation:** Repeat across every promotion sharing the same reward token to drain all tokens.
**Insight:** When a contract trusts an externally-supplied address for accounting inputs, check whether the only gate is an interface/ERC165 check — attacker-controlled implementations can return arbitrary values into reward or share math.
