Core Contracts

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

RAACHousePrices contract can provide misleading pricing data and break the lending functionality

Summary

Race condition vulnerability in RAACHousePriceOracle where multiple oracle requests can lead to incorrect house price updates due to shared state variable (lastHouseId).

Vulnerability Details

The RAACHousePriceOracle contract contains a race condition vulnerability related to the lastHouseId state variable. This occurs because multiple concurrent Chainlink Functions requests can overwrite lastHouseId before previous responses are processed, leading to incorrect price updates.

Detailed Explanation of the Vulnerability

  1. Flow of Requests and Responses:

    • When sendRequest() is called, it triggers _beforeFulfill(args), which sets lastHouseId using the first argument (args[0]).

    • The request is sent to Chainlink, and the response is handled asynchronously by fulfillRequest().

    • The _processResponse() function uses lastHouseId to update the house price, assuming it matches the original request.

  2. Race Condition Scenario:

    • Request A is sent with args[0] = 123. lastHouseId is set to 123.

    • Before Request A's response arrives, Request B is sent with args[0] = 456. lastHouseId is updated to 456.

    • If Response B is processed first, it correctly updates the price for house 456.

    • When Response A arrives later, lastHouseId is now 456, so the price for house 123 is erroneously applied to house 456.

  3. Root Cause:

    • lastHouseId is a single global variable shared across all requests.

    • There is no mechanism to correlate responses with their original requests (e.g., request IDs or mapping).

    • If multiple requests are in flight, the final value of lastHouseId depends on the order of responses, not the order of requests.

Here is simplified example:

  1. Alice calls sendRequest(123)

    • lastId = 123

  2. Before response comes, Bob calls sendRequest(456)

    • lastId = 456

  3. Bob's response arrives first:

    • fulfillRequest(100) → Sets prices[456] = 100

  4. Alice's response arrives later:

    • fulfillRequest(200) → Sets prices[456] = 200

    • Alice's price was applied to Bob's ID!

Impact

The vulnerability has severe implications for the lending:

  • getUserCollateralValue() may return wrong total value. This could allow users to borrow more than their collateral allows or prevent legitimate borrowing due to undervalued collateral

  • borrow() function relies on collateral value checks. Wrong prices could bypass the check: collateralValue < userTotalDebt.percentMul(liquidationThreshold). Potential protocol insolvency risk

  • Blocked Withdrawals. withdrawNFT() might incorrectly block/allow NFT withdrawals

  • Users might be unable to withdraw their NFTs or withdraw when they shouldn't

Tools Used

Manual review

Recommendations

Store requestid and lastHouseId in a map.

Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Oracle Race Condition in RAACHousePriceOracle causes price misassignment between NFTs

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Oracle Race Condition in RAACHousePriceOracle causes price misassignment between NFTs

Support

FAQs

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