Core Contracts

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

Incorrect Timestamp Tracking in RAACHousePrice contract

Description

The RAACHousePrices contract tracks house prices and their update timestamps for each token ID. The contract uses a single global lastUpdateTimestamp variable for all tokens, causing the timestamp of previous token updates to be overwritten when any token's price is created or updated.

function setHousePrice(
uint256 _tokenId,
uint256 _amount
) external onlyOracle {
tokenToHousePrice[_tokenId] = _amount;
@> lastUpdateTimestamp = block.timestamp; // Overwrites timestamp for all tokens
emit PriceUpdated(_tokenId, _amount);
}

Risk

Likelihood: High

  • Each time an house price is set or updated, it overwrites the timestamp of all other tokens

Impact: Low

  • Protocol returns incorrect timestamp information

Proof of Concept

function testGetLastestPriceFromHousePrices() public {
// Arrange
vm.startPrank(owner);
RAACHousePrices housePrices = new RAACHousePrices(owner);
housePrices.setOracle(owner);
vm.stopPrank();
uint256 tokenId = 1;
uint256 tokenId2 = 2;
uint256 price = 100 ether;
uint256 price2 = 200 ether;
// Act
address oracle = housePrices.oracle();
vm.startPrank(oracle);
housePrices.setHousePrice(tokenId, price);
vm.warp(block.timestamp + 30 days);
housePrices.setHousePrice(tokenId2, price2);
vm.stopPrank();
(, uint256 firstHousePriceTimestamp) = housePrices.getLatestPrice(tokenId);
console.log("firstHousePriceTimestamp", firstHousePriceTimestamp);
// firstHousePriceTimestamp >>> 1579392000
(, uint256 secondHousePriceTimestamp) = housePrices.getLatestPrice(tokenId2);
console.log("secondHousePriceTimestamp", secondHousePriceTimestamp);
//secondHousePriceTimestamp >>> 1579392000
// Assert
assertEq(firstHousePriceTimestamp, secondHousePriceTimestamp, "Timestamp should not be identical");
}

Recommended Mitigation

contract RAACHousePrices {
- mapping(uint256 => uint256) public tokenToHousePrice;
- uint256 public lastUpdateTimestamp;
+ struct PriceData {
+ uint256 price;
+ uint256 timestamp;
+ }
+ mapping(uint256 => PriceData) public tokenToPriceData;
function setHousePrice(uint256 _tokenId, uint256 _price) external onlyOracle {
- tokenToHousePrice[tokenId] = price;
- lastUpdateTimestamp = block.timestamp;
+ tokenToPriceData[_tokenId] = PriceData({
+ price: _price,
+ timestamp: block.timestamp
+ });
}
function getLatestPrice(uint256 _tokenId) external view returns (uint256, uint256) {
- return (tokenToHousePrice[_tokenId], lastUpdateTimestamp);
+ PriceData memory data = tokenToPriceData[_tokenId];
+ return (data.price, data.timestamp);
}
}
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!