# Adversary can brick bounty payouts by calling fundBountyToken but funding it with an ERC721 token instead

OpenQ's _receiveERC20 accepts ERC721 tokens since transferFrom/balanceOf signatures overlap, but payouts use transfer(), permanently bricking the bounty.

- Payout: Contest reward
- Severity: high
- Program: Openq
- Credited: XKET
- Disclosed: 2023-01-30
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-02-openq-judging/issues/352
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-02-openq%3AH-2
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:sherlock sev:high tech:solidity technique:source-review vuln:business-logic vuln:dos

**Target:** BountyCore funding/payout contract
**Root cause:** _receiveERC20 only calls transferFrom and balanceOf, which ERC721 also implements (with tokenId as amount), so an NFT passes the ERC20 funding path; payout uses transfer(), absent on ERC721, so every payout reverts.
**Steps:**
1. Call fundBountyToken with a whitelisted ERC721 token address and tokenId as the amount
2. _receiveERC20 executes `transferFrom(funder, bounty, tokenId)` and `balanceOf(bounty)` — both succeed on ERC721
3. Bounty now records the NFT as a reward token
4. Any claim/payout iterates tokens and calls `transfer(...)` on the NFT, which reverts
5. All payouts from the bounty revert permanently; combined with refund locking, funds stuck
**How found:** Code reading: noticed _receiveERC20's transferFrom/balanceOf calls are signature-compatible with ERC721, while the withdrawal path uses transfer() which ERC721 lacks — a token-standard interface mismatch.
**Exploitation:** Attacker funds a bounty with an ERC721 token id via the ERC20 funding path; the deposit succeeds but the token cannot be transferred out, so every subsequent payout call reverts, bricking the bounty and trapping other deposited ERC20s.
**Escalation:** Combined with refund-locking methods to make all deposited tokens permanently stuck.
**Insight:** When a contract treats any whitelisted token as ERC20, check whether ERC721/ERC1155 share the exact function selectors used on deposit but not on withdrawal; a deposit-only-compatible token bricks the whole payout loop.
