Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: high
Invalid

Unvalidated request ID in `BaseChainlinkFunctionsOracle::fulfillRequest` function

Summary

The BaseChainlinkFunctionsOracle::fulfillRequest function in the smart contract does not validate the requestId parameter before processing the response. This allows outdated responses to override the latest one, leading to unintended behavior and inaccurate price updates.

Vulnerability Details

The BaseChainlinkFunctionsOracle::fulfillRequest function is responsible for processing the responses from Chainlink. However, it does not verify whether the requestId matches the expected s_lastRequestId before storing the response and error values:

function fulfillRequest(
bytes32 requestId,
bytes memory response,
bytes memory err
) internal override {
// @audit-issue do not verify s_lastRequestId
s_lastResponse = response;
s_lastError = err;
if (err.length == 0) {
if (response.length == 0) {
revert FulfillmentFailed();
}
_processResponse(response);
}
}

Code Reference: https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/oracles/BaseChainlinkFunctionsOracle.sol#L99

According to Chainlink’s official documentation, a proper implementation should include request ID verification:

function fulfillRequest(
bytes32 requestId,
bytes memory response,
bytes memory err
) internal override {
// Verify the s_lastRequestId
if (s_lastRequestId != requestId) {
revert UnexpectedRequestID(requestId);
}
s_lastResponse = response;
s_lastError = err;
emit Response(requestId, s_lastResponse, s_lastError);
}

Documentation Reference: https://docs.chain.link/chainlink-functions/tutorials/abi-decoding#examine-the-code

The issue occurs in the following sequence:

  1. The owner calls sendRequest, receiving s_lastRequestId = 3.

  2. The owner calls sendRequest again, updating s_lastRequestId to 4.

  3. Due to execution delays, Chainlink fulfills request ID 4 first and updates the response.

  4. Chainlink then fulfills request ID 3, which is outdated but still processed because there is no validation.

  5. The outdated response overwrites the correct response, leading to incorrect price updates and potential financial loss.

Impact

  • Incorrect Data Updates: The contract may store an outdated response, leading to incorrect decision-making in dependent logic.

  • Financial Risks: If price updates are used for financial transactions, an outdated response could result in mispriced trades or inaccurate settlements.

Tools Used

Manual Review

Recommendations

To mitigate this issue, implement a request ID validation check in BaseChainlinkFunctionsOracle::fulfillRequest as follows:

function fulfillRequest(
bytes32 requestId,
bytes memory response,
bytes memory err
) internal override {
+ require(s_lastRequestId == requestId, "Unexpected request ID");
s_lastResponse = response;
s_lastError = err;
if (err.length == 0) {
if (response.length == 0) {
revert FulfillmentFailed();
}
_processResponse(response);
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope
inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope

Support

FAQs

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