# When rewardToken is erc1155/erc777, an attacker can reenter and cause funds to be stuck in the contract forever

Reentrancy via ERC1155/ERC777 reward token callback desyncs redeemedTokens accounting in Quest.claim, causing withdrawRemainingTokens to revert or leak funds.

- Payout: Contest reward
- Severity: medium
- Program: RabbitHole
- Credited: simon135
- Disclosed: 2023-04-11
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-01-rabbithole-findings/issues/523
- Library page: https://bugbountylibrary.com/r/c4%3A2023-01-rabbithole%3AM-05
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:reentrancy

**Target:** Quest.sol claim/withdrawRemainingTokens reward distribution contract
**Root cause:** claim() transfers reward tokens before updating redeemedTokens and lacks a reentrancy guard; ERC1155/ERC777 transfer callbacks let the recipient reenter claim with another receipt token, so redeemedTokens undercounts actual redemptions.
**Steps:**
1. Deploy attacker contract holding receipt token #1; approve receipt token #2 to it from Alice's EOA.
2. Attacker contract calls `claim()` on Quest.
3. During `safeTransferFrom` reward payout, `onERC1155Received`/ERC777 hook fires; callback transfers approved receipt token #2 into attacker contract.
4. Reenter `claim()` for token #2 before outer call updates `redeemedTokens`.
5. Observe `redeemedTokens` incremented once but two rewards paid; call `withdrawRemainingTokens` and see `unclaimedTokens` overestimated, causing underflow revert or stuck funds.
**How found:** Code reading of claim() noting reward transfer precedes state update and no nonReentrant modifier, combined with knowledge that ERC1155/ERC777 invoke receiver hooks during transfer.
**Exploitation:** Attacker needs two receipt tokens (one held by a contract, one approved to it). Reentering claim during the reward token transfer callback double-redeems while redeemedTokens only increments once, inflating unclaimedTokens in withdrawRemainingTokens so nonClaimableTokens underflows and reverts, locking remaining funds; repeated reentrancy widens the gap.
**Escalation:** Multiple reentrant claims across many quests widen the redeemedTokens discrepancy, increasing stuck funds.
**Insight:** When auditing reward/claim flows, check whether token transfer (especially ERC1155/ERC777 with receiver hooks) happens before accounting updates; the callback is a reentry point even without an explicit external call.
