Weather Witness

First Flight #40
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Missing Withdrawal Function Locks Ether

Contract Locks Ether in `WeatherNft::requestMintWeatherNFT` Without Withdrawal Mechanism

Description

  • The requestMintWeatherNFT function allows users to send ETH to the contract to pay for minting an NFT. The contract lacks a mechanism to withdraw these funds, causing all received ETH to be permanently locked.

function requestMintWeatherNFT(string memory _pincode, string memory _isoCode, bool _registerKeeper, uint256 _heartbeat, uint256 _initLinkDeposit)
external
payable
returns (bytes32 _reqId)
{
require(msg.value == s_currentMintPrice, WeatherNft__InvalidAmountSent()); // @> Accepts ETH without withdrawal
s_currentMintPrice += s_stepIncreasePerMint;
_reqId = _sendFunctionsWeatherFetchRequest(_pincode, _isoCode);
s_funcReqIdToUserMintReq[_reqId] = UserMintRequest(msg.sender, _pincode, _isoCode, _registerKeeper, _heartbeat, _initLinkDeposit);
emit MintRequest(_reqId, msg.sender);
}

Risk

Likelihood:

  • Users send ETH with every mint request, as required by the contract.

  • The absence of a withdrawal function ensures funds remain locked after each transaction.

Impact:

  • Permanent loss of ETH (e.g., 1 ETH per mint) for the project owner.

  • Reduced user trust due to inaccessible fees, potentially deterring participation.

Proof of Concept

  1. User calls requestMintWeatherNFT with msg.value = s_currentMintPrice.

  2. ETH is stored in the contract, but no function allows withdrawal.

function testEtherLocked() public {
uint256 mintPrice = weatherNft.getCurrentMintPrice();
vm.deal(user, mintPrice);
vm.prank(user);
weatherNft.requestMintWeatherNFT{value: mintPrice}("12345", "US", false, 1 hours, 0);
assertEq(address(weatherNft).balance, mintPrice);
}

Recommended Mitigation

Add a withdrawal function:

+ function withdraw() external onlyOwner {
+ (bool success, ) = payable(owner()).call{value: address(this).balance}("");
+ require(success, "Withdrawal failed");
+ }
Updates

Appeal created

bube Lead Judge 4 days ago
Submission Judgement Published
Validated
Assigned finding tags:

Lack of `withdraw` function

The contract collects funds for minting a WeatherNFT, but there is no function that allows the owner to withdraw these funds.

Support

FAQs

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