# Adding NFTS with AssociationType ORDERED or PRIMARY may cause overwriting

CidNFT.add overwrites ORDERED/PRIMARY association slots without checking, trapping the previously added subprotocol NFT in the contract forever.

- Payout: Contest reward
- Severity: medium
- Program: Canto Identity Protocol
- Credited: hihen
- Disclosed: 2023-04-06
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-01-canto-identity-findings/issues/187
- Library page: https://bugbountylibrary.com/r/c4%3A2023-01-canto-identity%3AM-01
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic

**Target:** CidNFT.add() association storage (ordered/primary mappings)
**Root cause:** add() writes cidData ordered[_key] and primary directly without verifying the slot is empty, so a second add for the same key/subprotocol silently overwrites the prior NFT ID.
**Steps:**
1. Mint two subprotocol NFTs nft1, nft2 to user; approve CidNFT.
2. Mint a CidNFT; call `cidNFT.add(cid, "sub1", key, nft1, ORDERED)`.
3. Call `cidNFT.add(cid, "sub1", key, nft2, ORDERED)` with same key — overwrites slot.
4. Both NFTs are held by CidNFT; `remove` for nft2 succeeds, `remove` for nft1 reverts OrderedValueNotSet, nft1 trapped.
5. Same flow with PRIMARY type: second add overwrites primary, first NFT unrecoverable.
**How found:** Code reading of add()'s ORDERED/PRIMARY branches revealed direct storage writes with no prior-slot emptiness check, unlike the ACTIVE branch which checks ActiveArrayAlreadyContainsID.
**Exploitation:** User (or anyone authorized) adds a second NFT to the same ordered key or primary slot; the first NFT's ID is lost from storage while the token remains escrowed in CidNFT, making it permanently unrecoverable via remove().
**Insight:** When a contract has multiple association types, compare their write paths: the ACTIVE branch guarded against duplicates while ORDERED/PRIMARY did not — asymmetric validation between sibling branches is a reliable overwrite-bug signal.
