# when reservedUntilTokenId > 100 first funder loss 1% NFT

Nounsbuilder initialized founder baseTokenId to reservedUntilTokenId; when >100 the first scheduled slot lands out of range, costing the first founder 1% of NFTs.

- Payout: Contest reward
- Severity: high
- Program: Nounsbuilder
- Credited: 0x52
- Disclosed: 2023-09-14
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-09-nounsbuilder-judging/issues/42
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-09-nounsbuilder%3AH-1
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Token.sol founder scheduling (_addFounders/_getNextTokenId/_isForFounder)
**Root cause:** _addFounders sets baseTokenId = reservedUntilTokenId instead of 0; _getNextTokenId only wraps modulo 100 on increment, so a starting value >100 stores tokenRecipient[200] which _isForFounder (tokenId % 100) can never reach.
**Steps:**
1. Deploy token with reservedUntilTokenId=200 and founder[0].founderPct=10
2. _addFounders: baseTokenId=200; _getNextTokenId(200) returns 200 since tokenRecipient[200] empty; tokenRecipient[200]=founder
3. Next iteration baseTokenId=(200+10)%100=10; slots 10,20,...,90 assigned
4. _isForFounder computes baseTokenId=_tokenId%100, so slot 200 is never consulted; founder only receives 9 of 10 scheduled slots
5. POC: make tokenRecipient public, deployAltMock(200), assert tokenRecipient(200).wallet==founder
**How found:** Code reading of _addFounders vs _isForFounder: noticed baseTokenId seeded from reservedUntilTokenId while lookup always mods by 100, so any seed >100 creates an unreachable slot.
**Insight:** When a mapping is indexed by id%100 at read time, audit every write path for seeds that bypass the modulo; a single un-wrapped initial value silently orphans a slot.
