Weather Witness

First Flight #40
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Missing Input Validation in requestMintWeatherNFT Function

Summary

The requestMintWeatherNFT function in the WeatherNft contract lacks proper input validation for critical parameters including pincode, isoCode, heartbeat interval, and initial LINK deposit, potentially allowing invalid data to be stored or excessive LINK deposits.

Vulnerability Details

The function accepts several parameters without validation:

function requestMintWeatherNFT(
string memory _pincode,
string memory _isoCode,
bool _registerKeeper,
uint256 _heartbeat,
uint256 _initLinkDeposit
) external payable returns (bytes32 _reqId) {
// No validation for _pincode or _isoCode
// No minimum check for _heartbeat
// No maximum check for _initLinkDeposit
}

This could lead to:

  • Invalid location data being stored (empty or malformed pincode/isoCode)

  • Extremely short heartbeat intervals causing excessive Chainlink Function calls

  • Excessive LINK deposits that could be locked in the contract

Proof of Concept

// SPDX-License-Identifier: MIT
pragma solidity 0.8.29;
import "forge-std/Test.sol";
import "../src/WeatherNft.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract InputValidationTest is Test {
WeatherNft public weatherNft;
address public user;
IERC20 public linkToken;
function setUp() public {
// Setup the WeatherNft contract and necessary dependencies
// This would include deploying the contract and setting up any required configurations
// For this PoC, we assume weatherNft is already deployed
weatherNft = WeatherNft(address(0x123)); // Replace with actual address
linkToken = IERC20(address(0x456)); // Replace with LINK token address
user = address(0x789); // User address
// Fund the user with ETH and LINK
vm.deal(user, 10 ether);
// Assume user has LINK tokens and has approved the WeatherNft contract
}
function testEmptyPincode() public {
vm.startPrank(user);
// Get the current mint price
uint256 mintPrice = weatherNft.s_currentMintPrice();
// Approve LINK tokens
linkToken.approve(address(weatherNft), 1 ether);
// Attempt to mint with empty pincode
weatherNft.requestMintWeatherNFT{value: mintPrice}(
"", // Empty pincode
"US",
true,
3600,
0.1 ether
);
// This should succeed despite empty pincode
// In a properly validated contract, this should revert
vm.stopPrank();
}
function testZeroHeartbeat() public {
vm.startPrank(user);
// Get the current mint price
uint256 mintPrice = weatherNft.s_currentMintPrice();
// Approve LINK tokens
linkToken.approve(address(weatherNft), 1 ether);
// Attempt to mint with zero heartbeat
weatherNft.requestMintWeatherNFT{value: mintPrice}(
"12345",
"US",
true,
0, // Zero heartbeat
0.1 ether
);
// This should succeed despite zero heartbeat
// In a properly validated contract, this should revert
vm.stopPrank();
}
function testExcessiveLinkDeposit() public {
vm.startPrank(user);
// Get the current mint price
uint256 mintPrice = weatherNft.s_currentMintPrice();
// Approve LINK tokens
linkToken.approve(address(weatherNft), 1000 ether);
// Attempt to mint with excessive LINK deposit
weatherNft.requestMintWeatherNFT{value: mintPrice}(
"12345",
"US",
true,
3600,
1000 ether // Excessive LINK deposit
);
// This should succeed despite excessive LINK deposit
// In a properly validated contract, this should revert
vm.stopPrank();
}
function testInvalidIsoCode() public {
vm.startPrank(user);
// Get the current mint price
uint256 mintPrice = weatherNft.s_currentMintPrice();
// Approve LINK tokens
linkToken.approve(address(weatherNft), 1 ether);
// Attempt to mint with invalid ISO code
weatherNft.requestMintWeatherNFT{value: mintPrice}(
"12345",
"INVALID_TOO_LONG", // Invalid ISO code (too long)
true,
3600,
0.1 ether
);
// This should succeed despite invalid ISO code
// In a properly validated contract, this should revert
vm.stopPrank();
}
}

This PoC demonstrates how the lack of input validation allows users to create NFTs with invalid or problematic parameters, which could lead to various issues in the system.

Impact

The lack of input validation could result in:

  • NFTs with invalid or unusable location data

  • Excessive consumption of LINK tokens due to too-frequent updates

  • Economic losses for users who deposit more LINK than necessary

  • Potential DoS conditions if many NFTs are created with very short heartbeat intervals

Recommendations

Implement proper input validation for all parameters:

function requestMintWeatherNFT(
string memory _pincode,
string memory _isoCode,
bool _registerKeeper,
uint256 _heartbeat,
uint256 _initLinkDeposit
) external payable returns (bytes32 _reqId) {
// Validate inputs
require(bytes(_pincode).length > 0, "WeatherNft__InvalidPincode");
require(bytes(_isoCode).length > 0, "WeatherNft__InvalidIsoCode");
require(_heartbeat >= MIN_HEARTBEAT, "WeatherNft__HeartbeatTooShort");
require(_initLinkDeposit <= MAX_LINK_DEPOSIT, "WeatherNft__ExcessiveLinkDeposit");
// Rest of the function...
}

Define appropriate constants for minimum heartbeat and maximum LINK deposit based on the system's requirements.

Updates

Appeal created

bube Lead Judge 7 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

[Invalid] Lack of input validation in `requestMintWeatherNFT`

This is informational. It is user's responsibility to provide correct input arguments. If the user provides incorrect arguments, it will lead to incorrect results, lost funds or failed transaction.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.