Skip to content
This repository has been archived by the owner on Jun 2, 2024. It is now read-only.

KingNFT - Founders could still obtain vesting NFTs even when they have been intentionally removed by the contract owner #259

Closed
sherlock-admin2 opened this issue Dec 1, 2023 · 7 comments
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Escalation Resolved This issue's escalations have been approved/rejected High A valid High severity issue Reward A payout will be made for this issue

Comments

@sherlock-admin2
Copy link
Contributor

sherlock-admin2 commented Dec 1, 2023

KingNFT

high

Founders could still obtain vesting NFTs even when they have been intentionally removed by the contract owner

Summary

The incorrect implementation of updateFounders() would cause that founders could still claim vesting NFTs even when they have been intentionally removed by the contract owner.

Vulnerability Detail

The issue arises on L412, the baseTokenId should begin with reservedUntilTokenId % 100.

File: src\token\Token.sol
375:     function updateFounders(IManager.FounderParams[] calldata newFounders) external onlyOwner {
...
393:         unchecked {
394:             // for each existing founder:
395:             for (uint256 i; i < cachedFounders.length; ++i) {
...
407: 
408:                 // using the ownership percentage, get reserved token percentages
409:                 uint256 schedule = 100 / cachedFounder.ownershipPct;
410: 
411:                 // Used to reverse engineer the indices the founder has reserved tokens in.
-412:                 uint256 baseTokenId; // @audit should begin with reservedUntilTokenId
+412:                 uint256 baseTokenId = reservedUntilTokenId % 100;
413: 
414:                 for (uint256 j; j < cachedFounder.ownershipPct; ++j) {
415:                     // Get the next index that hasn't already been cleared
416:                     while (clearedTokenIds[baseTokenId] != false) {
417:                         baseTokenId = (++baseTokenId) % 100;
418:                     }
419: 
420:                     delete tokenRecipient[baseTokenId];
421:                     clearedTokenIds[baseTokenId] = true;
422: 
423:                     emit MintUnscheduled(baseTokenId, i, cachedFounder);
424: 
425:                     // Update the base token id
426:                     baseTokenId = (baseTokenId + schedule) % 100;
427:                 }
428:             }
429:         }
...
437:     }

let's say the reservedUntilTokenId == 10 and founderPct = 5, when _addFounders() in initialize(), the following tokenRecipients would be set.

tokenRecipient[10]
tokenRecipient[30]
tokenRecipient[50]
tokenRecipient[70]
tokenRecipient[90]

But in updateFounders(), as baseTokenId begin with 0, the actual cleared tokenRecipients are

tokenRecipient[0]
tokenRecipient[20]
tokenRecipient[40]
tokenRecipient[60]
tokenRecipient[80]

We can see, none of previous valid tokenRecipient info is cleared. Hence, founders could still obtain those vesting NFTs.

Impact

Founders could still claim vesting NFTs even when they have been intentionally removed.

Code Snippet

https://github.com/sherlock-audit/2023-09-nounsbuilder/blob/main/nouns-protocol/src/token/Token.sol#L412

Tool used

Manual Review

Recommendation

see Vulnerability Detail

Duplicate of #42

@github-actions github-actions bot closed this as completed Dec 6, 2023
@github-actions github-actions bot added High A valid High severity issue Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label labels Dec 6, 2023
@sherlock-admin sherlock-admin changed the title Hidden Amber Wolverine - Founders could still obtain vesting NFTs even when they have been intentionally removed by the contract owner KingNFT - Founders could still obtain vesting NFTs even when they have been intentionally removed by the contract owner Dec 13, 2023
@sherlock-admin sherlock-admin added the Reward A payout will be made for this issue label Dec 13, 2023
@ydspa
Copy link

ydspa commented Dec 13, 2023

Escalate

This is not dup of #42, with both different affected function and different impact.

@sherlock-admin2
Copy link
Contributor Author

sherlock-admin2 commented Dec 13, 2023

Escalate

This is not dup of #42, with both different affected function and different impact.

You've created a valid escalation!

To remove the escalation from consideration: Delete your comment.

You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.

@sherlock-admin sherlock-admin added the Escalated This issue contains a pending escalation label Dec 13, 2023
@nevillehuang
Copy link
Collaborator

Will review all duplicates under #42, so please check deduplication comments here in the mean time.

@nevillehuang
Copy link
Collaborator

See comment here

@Czar102
Copy link

Czar102 commented Dec 20, 2023

I agree with the Lead Judge, planning to leave the issue as is. @ydspa please let me know if the logic in the above comment makes sense.

@Czar102
Copy link

Czar102 commented Dec 21, 2023

Result:
High
Duplicate of #42

@sherlock-admin2 sherlock-admin2 removed the Escalated This issue contains a pending escalation label Dec 21, 2023
@sherlock-admin sherlock-admin added the Escalation Resolved This issue's escalations have been approved/rejected label Dec 21, 2023
@sherlock-admin2
Copy link
Contributor Author

Escalations have been resolved successfully!

Escalation status:

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Escalation Resolved This issue's escalations have been approved/rejected High A valid High severity issue Reward A payout will be made for this issue
Projects
None yet
Development

No branches or pull requests

5 participants