Weather Witness

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

Lack of Emergency Stop Mechanism in Weather NFT Contract

Description

The contract lacks a pause mechanism, preventing the ability to halt operations during emergencies or when vulnerabilities are discovered.

Risk

Severity: High
Likelihood: Medium

Summary

The requestMintWeatherNFT and other critical functions lack pause protection, making it impossible to stop malicious activities or protect users during emergencies.

Vulnerability Details

Root Cause: Absence of pause modifier and pause control mechanism in the contract architecture.

Initial State: Contract operates continuously without ability to halt.

Attack Scenario:

  1. A vulnerability is discovered in the contract

  2. Attacker begins exploiting the vulnerability

  3. Contract owner has no mechanism to prevent further exploitation

  4. Users continue to lose funds while fix is prepared

Proof of Concept

// Attacker can continue calling function even during known exploits
function attackVector() external {
bytes32 reqId;
// Attacker can repeatedly call this with no way to stop
while (true) {
reqId = weatherNft.requestMintWeatherNFT(
"123456",
"US",
false,
3600,
1e18
);
}
}

Impact

  • No way to prevent losses during active exploits

  • Contract owner powerless during emergencies

  • Users funds at constant risk

  • Increased liability for protocol

Tools Used

  • Manual Review

  • Static Analysis

Recommendations

Add pause mechanism with granular control:

contract WeatherNft is WeatherNftStore, ERC721, FunctionsClient, ConfirmedOwner, AutomationCompatibleInterface, Pausable {
// ...existing code...
modifier whenContractActive() {
require(!paused(), "Contract is paused");
_;
}
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
function requestMintWeatherNFT(
string memory _pincode,
string memory _isoCode,
bool _registerKeeper,
uint256 _heartbeat,
uint256 _initLinkDeposit
) external payable whenContractActive returns (bytes32 _reqId) {
// ...existing code...
}
}

Alternative Implementation with Granular Pausing:

contract WeatherNft {
enum PauseType { MINTING, UPDATES, ALL }
mapping(PauseType => bool) public pauseStatus;
modifier whenNotPaused(PauseType pauseType) {
require(!pauseStatus[pauseType] && !pauseStatus[PauseType.ALL], "Operation paused");
_;
}
function setPauseStatus(PauseType pauseType, bool status) external onlyOwner {
pauseStatus[pauseType] = status;
emit PauseStatusChanged(pauseType, status);
}
}
Updates

Appeal created

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

Support

FAQs

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