# ownerMintUsingTokenId can brick the whole contract

Owner-only ownerMintUsingTokenId lets owner mint an arbitrary packed tokenId that collides with a future auto-generated ID, permanently reverting all subsequent mints and buys.

- Payout: Audit contest
- Severity: medium
- Program: Forgotten Runiverse
- Found by: Lambda
- Disclosed: 2023-12-01
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2022-12-forgotten-runiverse#m-02
- Library page: https://bugbountylibrary.com/r/c4%3A2022-12-forgotten-runiverse%3AM-02
- Tags: area:web3 domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:dos

**Target:** RuniverseLandMinter.sol ownerMintUsingTokenId / ownerGetNextTokenId
**Root cause:** ownerMintUsingTokenId mints an arbitrary tokenId without checking it against the packed [plotSize][localCounter][globalCounter] encoding used by ownerGetNextTokenId, so a pre-minted ID can equal a future auto-generated one; _mint then reverts on _exists.
**Steps:**
1. State: plotsMinted[0]=101, plotsMinted[1..4]=0, plotGlobalOffset=0.
2. Owner calls `ownerMintUsingTokenId` with tokenId `112150186059264` (= encoding [102][102][0]); this bumps plotsMinted[0] to 102.
3. User mints plot size 0; `_mintTokens` calls `ownerGetNextTokenId(0)` which returns `112150186059264`.
4. `runiverseLand.mintTokenId` calls `_mint`, which reverts on `require(!_exists(tokenId))`, so the mint fails.
**How found:** Reading ownerMintUsingTokenId and noticing tokenIds are packed encodings of plotSize/counters; hypothesized that an arbitrary owner-minted ID could equal a future ownerGetNextTokenId output, then computed a concrete colliding decimal.
**Exploitation:** Owner (privileged) mints a colliding ID, either accidentally or maliciously; every subsequent mint/buy for that plot size reverts, bricking minting. Owner can also encode plotSize IDs >4 not meant for sale.
**Insight:** When token IDs are packed structs of counters, any admin mint-by-raw-ID path must decode and validate the counters against the auto-increment state, otherwise a single mint can permanently collide with future IDs.

