Core Contracts

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

NFT Minting Price Validation Bypass Due to Unchecked Oracle Price

Summary

The RAACNFT contract's minting mechanism have a price validation vulnerability. When the oracle returns a zero price, the contract's validation logic can be bypassed, allowing NFTs to be minted at incorrect prices. This creates a systemic risk to the protocol's economic model.

For RAACNFT.sol#mint

function mint(uint256 _tokenId, uint256 _amount) public override {
// Critical oracle price check - needs additional validation layers
uint256 price = raac_hp.tokenToHousePrice(_tokenId);
// Basic zero check but lacks price bounds and staleness verification
if(price == 0) { revert RAACNFT__HousePrice(); }
// <<: Price comparison needs sanity bounds
if(price > _amount) { revert RAACNFT__InsufficientFundsMint(); }
// Token transfer happens before minting - good ordering
token.safeTransferFrom(msg.sender, address(this), _amount);
// NFT minting after payment verification - correct sequence
_safeMint(msg.sender, _tokenId);
// Refund logic needs gas consideration for large amounts
if (_amount > price) {
uint256 refundAmount = _amount - price;
token.safeTransfer(msg.sender, refundAmount);
}
emit NFTMinted(msg.sender, _tokenId, price);
}

For RToken.sol#mint()

function mint(
address caller,
address onBehalfOf,
uint256 amountToMint,
uint256 index
) external override onlyReservePool returns (bool, uint256, uint256, uint256) {
// Zero amount check - good
if (amountToMint == 0) {
return (false, 0, 0, 0);
}
// Critical scaling calculation - needs overflow protection
uint256 amountScaled = amountToMint.rayDiv(index);
// Valid check for scaled amount
if (amountScaled == 0) revert InvalidAmount();
// Balance tracking for first-time mints
uint256 scaledBalance = balanceOf(onBehalfOf);
bool isFirstMint = scaledBalance == 0;
// Interest calculation for existing holders
uint256 balanceIncrease = 0;
if (_userState[onBehalfOf].index != 0 && _userState[onBehalfOf].index < index) {
balanceIncrease = scaledBalance.rayMul(index) - scaledBalance.rayMul(_userState[onBehalfOf].index);
}
// State update before mint - correct ordering
_userState[onBehalfOf].index = index.toUint128();
// Actual minting operation with safe casting
_mint(onBehalfOf, amountToMint.toUint128());
emit Mint(caller, onBehalfOf, amountToMint, index);
return (isFirstMint, amountToMint, totalSupply(), amountScaled);
}

Vulnerability Details

The vulnerability centers on the price validation sequence in the mint function: RAACNFT.sol#L33-L35

uint256 price = raac_hp.tokenToHousePrice(_tokenId);
if(price == 0) { revert RAACNFT__HousePrice(); }
if(price > _amount) { revert RAACNFT__InsufficientFundsMint(); }

While there is a zero-price check, the contract lacks oracle price validation and sanity checks.

When an attacker observes the oracle returning a zero price for a tokenId. They can call mint() with a minimal amount. Despite the zero-price check, the transaction succeeds due to insufficient price validation, allowing NFT minting at an incorrect price point.

The issue lies in how the RAACNFT contract handles house price validations. Imagine a real estate agent selling houses without verifying the appraisal date, that's effectively what's happening here. When the oracle returns a price, the contract performs only basic validation, similar to accepting a house price without checking when it was last appraised.

Let's walk through how this plays out

An attacker monitors the oracle's price feeds, waiting for a moment when the tokenToHousePrice function returns zero for a valuable property. This is analogous to catching a glitch in a stock trading system where premium stocks briefly show as worthless. The attacker then calls the mint function with a minimal payment, exploiting the gap between the oracle update and price validation.

The contract's state transforms through three critical phases:

  1. The oracle reports a zero price for a legitimate property

  2. The basic zero-check passes due to insufficient validation

  3. The NFT mints at an incorrect valuation, undermining the entire property pricing model

This vulnerability could destabilize the protocol's real estate tokenization mechanism. Rather than just "financial loss," we're looking at the potential for attackers to acquire tokenized property rights at severely discounted prices, directly impacting the protocol's ability to maintain accurate property valuations.

Impact

The system allows minting NFTs when the oracle returns 0 price, potentially enabling:

  • Free minting of NFTs

  • Bypass of proper price validation

  • Economic exploitation of the protocol

function mint(uint256 _tokenId, uint256 _amount) public override {
uint256 price = raac_hp.tokenToHousePrice(_tokenId);
// Price validation happens after oracle call
// Zero price check exists but further validation needed
if(price == 0) { revert RAACNFT__HousePrice(); }

The mint function relies solely on the oracle price without additional validation safeguards or fallback mechanisms.The vulnerability centers on the price validation sequence in the mint function:

Recommendations

The solution requires implementing a price validation system that treats property valuations with the same rigor as traditional real estate transactions. Adding freshness checks, price bounds, and multiple oracle verifications, similar to how real estate transactions require recent appraisals from qualified sources.

function mint(uint256 _tokenId, uint256 _amount) public override {
uint256 price = raac_hp.tokenToHousePrice(_tokenId);
// Add minimum price threshold
if(price < MINIMUM_PRICE || price == 0) { revert RAACNFT__InvalidPrice(); }
// Add maximum price sanity check
if(price > MAXIMUM_PRICE) { revert RAACNFT__PriceExceedsMax(); }
Updates

Lead Judging Commences

inallhonesty Lead Judge about 2 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
inallhonesty Lead Judge about 2 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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