Weather Witness

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

performUpkeep Can Be Re-Entered — Drains LINK

Root + Impact

performUpkeep() does not enforce a mutex or cooldown, enabling potential reentrancy and LINK depletion.

Description

  • There’s no guard variable like requestInProgress or lastRequestTime.

  • Malicious actors or misconfigured keepers can re-trigger oracle requests quickly

function performUpkeep(bytes calldata) external {
sendRequest(location);
}

Risk

Likelihood:

  • Can be reentered in back-to-back transactions.

  • No time guard or flag prevents double request.

Impact:

  • LINK rapidly depleted by repeated oracle calls.

  • Denial-of-service for future users.

Proof of Concept

With insufficient spacing, both will queue different requests.

await weatherNft.performUpkeep("0x");
await weatherNft.performUpkeep("0x"); // Both trigger and charge LINK
// JS loop to call performUpkeep()
for (let i = 0; i < 5; i++) {
contract.performUpkeep("0x");
}

Recommended Mitigation

Add throttling with a timestamp and mutex calls:

uint256 public lastRequestTime;
bool public requestInProgress;
function performUpkeep(bytes calldata) external {
require(block.timestamp > lastRequestTime + 5 minutes, "Too soon");
require(!requestInProgress, "Already requested");
requestInProgress = true;
lastRequestTime = block.timestamp;
sendRequest(location);
}
Updates

Appeal created

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

Anyone can call `performUpkeep` function

The `performUpkeep` function should be called by the Chainlink keepers or owners of the NFT. But there is no access control and anyone can call the function. This leads to malicious consumption of the user's LINK deposit.

Support

FAQs

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