Core Contracts

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

`RAACHousePrices` Updates `lastUpdateTimestamp` For Every House Token When `RAACHousePrices::setHousePrice` Is Called

Summary

The RAACHousePrices contract uses a single global lastUpdateTimestamp variable to track price updates across all tokens, rather than maintaining individual timestamps for each token. This causes tokens to appear fresher than they actually are when prices are queried.

Vulnerability Details

[](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/primitives/RAACHousePrices.sol#L34-L37)

[](https://github.com/Cyfrin/2025-02-raac/blob/89ccb062e2b175374d40d824263a4c0b601bcb7f/contracts/core/primitives/RAACHousePrices.sol#L49-L55)

The contract tracks price updates using a single global timestamp:

uint256 public lastUpdateTimestamp;
function getLatestPrice(
uint256 _tokenId
) external view returns (uint256, uint256) {
return (tokenToHousePrice[_tokenId], lastUpdateTimestamp);
}
function setHousePrice(uint256 _tokenId, uint256 _amount) external onlyOracle {
tokenToHousePrice[_tokenId] = _amount;
lastUpdateTimestamp = block.timestamp; // Updates global timestamp
emit PriceUpdated(_tokenId, _amount);
}

When the oracle updates any token's price, it updates this global timestamp. This means if Token A is updated at t=100 and Token B at t=200, Token A will appear to have been updated at t=200 when queried via RAACHousePrices::getLatestPrice.

Impact

  • Price staleness cannot be accurately tracked per token

  • LendingPool::getNFTPrice could use stale prices thinking they're fresh

  • Direct financial impact through lending decisions based on stale data

Tools Used

  • Manual code review

  • Flow analysis through contracts

Recommendations

Implement per-token timestamps:

+ mapping(uint256 => uint256) public tokenLastUpdateTimestamp;
function getLatestPrice(
uint256 _tokenId
) external view returns (uint256, uint256) {
- return (tokenToHousePrice[_tokenId], lastUpdateTimestamp);
+ return (tokenToHousePrice[_tokenId], tokenLastUpdateTimestamp[_tokenId]); // Return token-specific timestamp
}
function setHousePrice(uint256 _tokenId, uint256 _amount) external onlyOracle {
tokenToHousePrice[_tokenId] = _amount;
- lastUpdateTimestamp = block.timestamp;
+ tokenLastUpdateTimestamp[_tokenId] = block.timestamp;
emit PriceUpdated(_tokenId, _amount);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 2 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 about 2 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.