Weather Witness

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

Front-running Mint Requests

Root: The function emits a predictable request ID (_reqId) before storing associated minting information, allowing bots or malicious actors to track and act on it.

Impact: An attacker could front-run the asynchronous process and attempt to spoof or fulfill the request before the legitimate user, leading to the minting of a weather NFT with incorrect or manipulated weather metadata.

Description

  • Normally, the contract sends a Chainlink Functions request and maps the resulting request ID to the user’s mint intent.

  • The request ID is emitted and accessible to everyone before internal mappings are secured, allowing attackers to exploit the delay.// Root cause in the codebase with @> marks to highlight the relevant section

Risk

Likelihood:

  • Request ID is visible to bots immediately after being created.

  • Exploitation possible before the mint is finalized.

Impact:

  • Wrong NFT metadata may be minted.

  • Trust in the minting process is broken—users may not get NFTs aligned with their actual location/weather.

Proof of Concept: This scenario shows that the user who submits a mint request second may either get their transaction reverted or unintentionally overpay because the global mint price was changed by someone else right before their transaction was mined. It exploits the mutable state of s_currentMintPrice.

// Attacker listens for emitted requestId on-chain.
// Before Chainlink fulfills, they attempt to guess or spoof a call to fulfillMintRequest
// with forged or replayed data for the same requestId.

Recommended Mitigation: The mitigation captures the request ID in a local variable first, and only after checking for collisions or duplicates does it update the mapping. This ensures internal state is committed before exposing data externally, preventing front-running. Using a temporary variable defers exposing the ID publicly until it is safe.

- _reqId = _sendFunctionsWeatherFetchRequest(_pincode, _isoCode);
- s_funcReqIdToUserMintReq[_reqId] = UserMintRequest({...});
+ bytes32 tempReqId = _sendFunctionsWeatherFetchRequest(_pincode, _isoCode);
+ require(s_funcReqIdToUserMintReq[tempReqId].user == address(0), "Duplicate Request");
+ s_funcReqIdToUserMintReq[tempReqId] = UserMintRequest({...});
+ _reqId = tempReqId;
Updates

Appeal created

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

Lack of ownership check in `fulfillMintRequest` function

There is no check to ensure that the caller of the `fulfillMintRequest` function is actually the owner of the `requestId`. This allows a malicious user to receive a NFT that is payed from someone else.

Support

FAQs

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