Core Contracts

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

Global Timestamp Mismanagement in RAACHousePrices Oracle

Impact

The RAACHousePrices oracle uses a single global lastUpdateTimestamp for all tokens. This means that whenever any token’s price is updated, the timestamp for every token is refreshed to the current time. As a result, tokens that haven't been updated recently may appear to have fresh prices, leading to misleading freshness data. This flaw can cause protocols relying on these timestamps to make decisions based on stale price data—potentially resulting in undercollateralized loans, inaccurate valuations, and other financial miscalculations.

Proof of Concept

  1. Affected Code:

    • RAACHousePrices.sol
      Link to code

      // Global timestamp used for all tokens
      uint256 public lastUpdateTimestamp;
      function getLatestPrice(uint256 _tokenId) external view returns (uint256, uint256) {
      return (tokenToHousePrice[_tokenId], lastUpdateTimestamp);
      }
    • Price Update Function:
      Link to code

      function setHousePrice(uint256 _tokenId, uint256 _amount) external onlyOracle {
      tokenToHousePrice[_tokenId] = _amount;
      lastUpdateTimestamp = block.timestamp; // Updates global timestamp
      emit PriceUpdated(_tokenId, _amount);
      }
  2. Issue Details:

    • Global Timestamp Issue:
      The oracle uses one lastUpdateTimestamp for all tokens. Updating the price for any single token resets the timestamp for every token.

    • Misleading Data:
      If a token's price has not been updated for an extended period, its data becomes stale. However, if another token is updated, the global lastUpdateTimestamp is refreshed, misleading any mechanism that checks for price freshness.

  3. Exploit Scenario:

    • Example:

      • Token A's price was last updated 30 days ago (and is stale).

      • Token B is updated today, which resets lastUpdateTimestamp to today for both tokens.

    • Impact:
      When a user queries Token A's price, the oracle returns the current timestamp, making it appear as if Token A's price is fresh. This can lead to erroneous price validations and potential borrowing against stale collateral.

Tools Used

  • Manual Review

Recommended Mitigation Steps

  1. Implement Token-Specific Timestamps:
    Replace the global lastUpdateTimestamp with a mapping that tracks each token's last update:

    struct PriceData {
    uint256 price;
    uint256 lastUpdateTimestamp;
    }
    mapping(uint256 => PriceData) public tokenPriceData;
  2. Update the Price Setting Function:
    Modify the setHousePrice function to update the timestamp for the specific token:

    function setHousePrice(uint256 _tokenId, uint256 _amount) external onlyOracle {
    tokenPriceData[_tokenId] = PriceData(_amount, block.timestamp);
    emit PriceUpdated(_tokenId, _amount);
    }
  3. Adjust the getLatestPrice Function:
    Ensure the function returns the token-specific timestamp:

    function getLatestPrice(uint256 _tokenId) external view returns (uint256, uint256) {
    PriceData memory data = tokenPriceData[_tokenId];
    return (data.price, data.lastUpdateTimestamp);
    }
Updates

Lead Judging Commences

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

RAACHousePrices uses a single global lastUpdateTimestamp for all NFTs instead of per-token tracking, causing misleading price freshness data

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

RAACHousePrices uses a single global lastUpdateTimestamp for all NFTs instead of per-token tracking, causing misleading price freshness data

Support

FAQs

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

Give us feedback!