When a user requests to mint an NFT with automated updates (_registerKeeper = true), they provide _initLinkDeposit as a uint256 value for funding the Chainlink Keeper. This full uint256 amount is transferred from the user to the WeatherNft contract.
However, when this deposit is used to register the upkeep in fulfillMintRequest, the amount field in IAutomationRegistrarInterface.RegistrationParams is a uint96. The contract code casts _userMintRequest.initLinkDeposit (which is uint256) to uint96 using uint96(_userMintRequest.initLinkDeposit).
If the user provides an _initLinkDeposit value larger than type(uint96).max, the value will be truncated. The Chainlink Automation registrar will only pull the truncated uint96 amount of LINK, but the contract has already received the full uint256 amount from the user and approved the full amount to the registrar. The difference (_initLinkDeposit - uint96(_initLinkDeposit)) remains in the WeatherNft contract, approved for the registrar but unutilized by the specific upkeep registration. Since there is no general mechanism to withdraw arbitrary LINK balances from the contract (only specific ones tied to upkeep management, if implemented), this excess LINK becomes permanently locked.
Likelihood: Medium
A user might accidentally or intentionally provide a _initLinkDeposit larger than type(uint96).max (approx 79.2 LINK if LINK has 18 decimals). This is not an extremely large sum, making it plausible for a user to deposit, especially if they are unsure about required funding and want to overfund significantly.
Front-ends or helper scripts might not validate this limit.
Impact: Medium
Permanent Loss of User's LINK: The portion of the LINK deposit exceeding type(uint96).max becomes locked in the contract and is irrecoverable by the user.
Reduced Capital Efficiency: User's funds are stuck.
Assume type(uint96).max is equivalent to 79 LINK (for simplicity, actual value is 2**96 - 1 wei).
Alice calls requestMintWeatherNFT with _registerKeeper = true and _initLinkDeposit = 100 * 10**18 (100 LINK).
The WeatherNft contract receives 100 LINK from Alice. _userMintRequest.initLinkDeposit is stored as 100 * 10**18.
In fulfillMintRequest, the contract approves s_keeperRegistrar for 100 * 10**18 LINK.
When preparing _keeperParams, amount is set to uint96(100 * 10**18). This truncates to 79 * 10**18 (approx).
registerUpkeep is called. The Chainlink Automation system funds the new upkeep with 79 * 10**18 LINK from the contract's balance (which was approved).
The remaining 100 - 79 = 21 LINK are still held by the WeatherNft contract. These 21 LINK are not associated with Alice's upkeep directly for spending and are not part of any refund or withdrawal mechanism related to this specific upkeep registration's overfunding. They are locked.
Validate _initLinkDeposit in requestMintWeatherNFT to ensure it does not exceed type(uint96).max. If it does, either revert the transaction or cap the deposit at type(uint96).max. Reverting is safer to ensure user intent is clear.
After discussion with the sponsor, this turns out to be invalid. This is because the Chainlink has a capped maximum supply of 1 billion LINK tokens. This means that the total number of LINK tokens will never exceed 1 billion. The token has 18 decimals, so the max scaled value that is required to represent all LINK tokens is 1e27. The max value of `uint96` is 2**96 - 1, that is around 79e27 and it is sufficient to store all LINK tokens. Therefore, the cast from uint256 to uint96 is safe and there is no possibility of token truncation/loss of tokens.
After discussion with the sponsor, this turns out to be invalid. This is because the Chainlink has a capped maximum supply of 1 billion LINK tokens. This means that the total number of LINK tokens will never exceed 1 billion. The token has 18 decimals, so the max scaled value that is required to represent all LINK tokens is 1e27. The max value of `uint96` is 2**96 - 1, that is around 79e27 and it is sufficient to store all LINK tokens. Therefore, the cast from uint256 to uint96 is safe and there is no possibility of token truncation/loss of tokens.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.