when reservedUntilTokenId > 100 first funder loss 1% NFT
The incorrect use of `baseTokenId = reservedUntilTokenId` may result in the first `tokenRecipient[]` being invalid, thus preventing the founder from obtaining this portion of the NFT.\\nThe current protocol adds a parameter `reservedUntilTokenId` for reserving `Token`. This parameter will be used as the starting `baseTokenId` during initialization.\\n```\\n    function _addFounders(IManager.FounderParams[] calldata _founders, uint256 reservedUntilTokenId) internal {\\n// rest of code\\n\\n                // Used to store the base token id the founder will recieve\\n              uint256 baseTokenId = reservedUntilTokenId;\\n\\n                // For each token to vest:\\n                for (uint256 j; j < founderPct; ++j) {\\n                    // Get the available token id\\n                    baseTokenId = _getNextTokenId(baseTokenId);\\n\\n                    // Store the founder as the recipient\\n                    tokenRecipient[baseTokenId] = newFounder;\\n\\n                    emit MintScheduled(baseTokenId, founderId, newFounder);\\n\\n                    // Update the base token id\\n                    baseTokenId = (baseTokenId + schedule) % 100;\\n                }\\n            }\\n..\\n\\n    function _getNextTokenId(uint256 _tokenId) internal view returns (uint256) {\\n        unchecked {\\n          while (tokenRecipient[_tokenId].wallet != address(0)) {\\n                _tokenId = (++_tokenId) % 100;\\n            }\\n\\n            return _tokenId;\\n        }\\n    }\\n```\\n\\nBecause `baseTokenId = reservedUntilTokenId` is used, if `reservedUntilTokenId>100`, for example, reservedUntilTokenId=200, the first `_getNextTokenId(200)` will return `baseTokenId=200 , tokenRecipient[200]=newFounder`.\\nExample: reservedUntilTokenId = 200 founder[0].founderPct = 10\\nIn this way, the `tokenRecipient[]` of `founder` will become tokenRecipient[200].wallet = `founder` ( first will call _getNextTokenId(200) return 200) tokenRecipient[10].wallet = `founder` ( second will call _getNextTokenId((200 + 10) %100 = 10) ) tokenRecipient[20].wallet = `founder` ... tokenRecipient[90].wallet = `founder`\\nHowever, this `tokenRecipient[200]` will never be used, because in `_isForFounder()`, it will be modulo, so only `baseTokenId < 100` is valid. In this way, the first founder can actually only `9%` of NFT.\\n```\\n    function _isForFounder(uint256 _tokenId) private returns (bool) {\\n        // Get the base token id\\n      uint256 baseTokenId = _tokenId % 100;\\n\\n        // If there is no scheduled recipient:\\n        if (tokenRecipient[baseTokenId].wallet == address(0)) {\\n            return false;\\n\\n            // Else if the founder is still vesting:\\n        } else if (block.timestamp < tokenRecipient[baseTokenId].vestExpiry) {\\n            // Mint the token to the founder\\n          _mint(tokenRecipient[baseTokenId].wallet, _tokenId);\\n\\n            return true;\\n\\n            // Else the founder has finished vesting:\\n        } else {\\n            // Remove them from future lookups\\n            delete tokenRecipient[baseTokenId];\\n\\n            return false;\\n        }\\n    }\\n```\\n\\nPOC\\nThe following test demonstrates that `tokenRecipient[200]` is for founder.\\nneed change tokenRecipient to public , so can assertEq\\n```\\ncontract TokenStorageV1 is TokenTypesV1 {\\n    /// @notice The token settings\\n    Settings internal settings;\\n\\n    /// @notice The vesting details of a founder\\n    /// @dev Founder id => Founder\\n    mapping(uint256 => Founder) internal founder;\\n\\n    /// @notice The recipient of a token\\n    /// @dev ERC// Remove the line below\\n721 token id => Founder\\n// Remove the line below\\n   mapping(uint256 => Founder) internal tokenRecipient;\\n// Add the line below\\n   mapping(uint256 => Founder) public tokenRecipient;\\n}\\n```\\n\\nadd to `token.t.sol`\\n```\\n    function test_lossFirst(address _minter, uint256 _reservedUntilTokenId, uint256 _tokenId) public {\\n        deployAltMock(200);\\n        (address wallet ,,)= token.tokenRecipient(200);\\n        assertEq(wallet,founder);\\n    }\\n```\\n\\n```\\n$ forge test -vvv --match-test test_lossFirst\\n\\nRunning 1 test for test/Token.t.sol:TokenTest\\n[PASS] test_lossFirst(address,uint256,uint256) (runs: 256, μ: 3221578, ~: 3221578)\\nTest result: ok. 1 passed; 0 failed; 0 skipped; finished in 355.45ms\\nRan 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)\\n```\\n
A better is that the baseTokenId always starts from 0.\\n```\\n    function _addFounders(IManager.FounderParams[] calldata _founders, uint256 reservedUntilTokenId) internal {\\n// rest of code\\n\\n                // Used to store the base token id the founder will recieve\\n// Remove the line below\\n               uint256 baseTokenId = reservedUntilTokenId;\\n// Add the line below\\n               uint256 baseTokenId =0;\\n```\\n\\nor\\nuse `uint256 baseTokenId = reservedUntilTokenId % 100;`\\n```\\n    function _addFounders(IManager.FounderParams[] calldata _founders, uint256 reservedUntilTokenId) internal {\\n// rest of code\\n\\n                // Used to store the base token id the founder will recieve\\n// Remove the line below\\n               uint256 baseTokenId = reservedUntilTokenId;\\n// Add the line below\\n               uint256 baseTokenId = reservedUntilTokenId  % 100;\\n```\\n
when reservedUntilTokenId > 100 first funder loss 1% NFT
```\\n    function _addFounders(IManager.FounderParams[] calldata _founders, uint256 reservedUntilTokenId) internal {\\n// rest of code\\n\\n                // Used to store the base token id the founder will recieve\\n              uint256 baseTokenId = reservedUntilTokenId;\\n\\n                // For each token to vest:\\n                for (uint256 j; j < founderPct; ++j) {\\n                    // Get the available token id\\n                    baseTokenId = _getNextTokenId(baseTokenId);\\n\\n                    // Store the founder as the recipient\\n                    tokenRecipient[baseTokenId] = newFounder;\\n\\n                    emit MintScheduled(baseTokenId, founderId, newFounder);\\n\\n                    // Update the base token id\\n                    baseTokenId = (baseTokenId + schedule) % 100;\\n                }\\n            }\\n..\\n\\n    function _getNextTokenId(uint256 _tokenId) internal view returns (uint256) {\\n        unchecked {\\n          while (tokenRecipient[_tokenId].wallet != address(0)) {\\n                _tokenId = (++_tokenId) % 100;\\n            }\\n\\n            return _tokenId;\\n        }\\n    }\\n```\\n