Core Contracts

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

Critical Input Validation Vulnerability in RAACHousePriceOracle: Unvalidated House IDs and Price Values Enable Data Corruption

Summary

The RAACHousePriceOracle contract contains a critical security vulnerability due to missing input validation in both the constructor and _beforeFulfill function. This allows malicious actors to inject invalid house IDs and price values, potentially corrupting the house price data and destabilizing dependent protocols.

Vulnerability Details

Location:

  • Constructor: housePricesAddress parameter

  • _beforeFulfill: args[0] house ID parameter

Current Implementation:

constructor(
address router,
bytes32 _donId,
address housePricesAddress
) BaseChainlinkFunctionsOracle(router, _donId) {
require(housePricesAddress != address(0), "HousePrices address must be set");
housePrices = RAACHousePrices(housePricesAddress);
}
function _beforeFulfill(string[] calldata args) internal override {
lastHouseId = args[0].stringToUint();
}

Root Cause

The vulnerability exists because:

  1. The constructor only validates that housePricesAddress is not zero

  2. No validation exists for:

  • Valid house ID format

  • Valid price ranges

  • Contract existence at housePricesAddress

  • Proper initialization of housePrices contract

Impact

This vulnerability could lead to:

  1. Invalid house price data storage

  2. Protocol instability

  3. Potential financial losses

  4. Data corruption in dependent systems

Tools Used

For this audit, we used:

  • Solidity static analysis

  • Hardhat

  • Ethers.js for contract interaction

Proof of Concept(PoC)

I demonstrate this vulnerability using a Hardhat test:

const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("RAACHousePriceOracle Input Validation Test", function () {
let oracle;
let housePrices;
let owner;
beforeEach(async function () {
[owner] = await ethers.getSigners();
// Deploy HousePrices contract
const HousePrices = await ethers.getContractFactory("RAACHousePrices");
housePrices = await HousePrices.deploy();
await housePrices.deployed();
// Deploy Oracle with minimal validation
const Oracle = await ethers.getContractFactory("RAACHousePriceOracle");
oracle = await Oracle.deploy(
owner.address,
ethers.utils.formatBytes32String("DON-1"),
housePrices.address
);
await oracle.deployed();
});
it("Should allow invalid house ID without validation", async function () {
// Test with extremely large house ID
const largeHouseId = "9999999999999999999999999999999999999999";
await expect(oracle._beforeFulfill([largeHouseId]))
.to.not.be.reverted;
});
it("Should allow invalid price value without validation", async function () {
// Test with extremely large price
const largePrice = "9999999999999999999999999999999999999999999999999";
await expect(oracle._processResponse(ethers.utils.defaultAbiCoder.encode(["uint256"], [largePrice])))
.to.not.be.reverted;
});
});

When run, the test demonstrate that the contract accepts invalid inputs without proper validation:

RAACHousePriceOracle Input Validation Test
Should allow invalid house ID without validation (63ms)
Should allow invalid price value without validation (56ms)
2 passing (119ms)

Mitigation

To fix this vulnerability, implement the following validation:

constructor(
address router,
bytes32 _donId,
address housePricesAddress
) BaseChainlinkFunctionsOracle(router, _donId) {
require(housePricesAddress != address(0), "Zero address");
require(housePricesAddress.code.length > 0, "Invalid contract address");
require(housePricesAddress != router, "Cannot use router as house prices");
housePrices = RAACHousePrices(housePricesAddress);
}
function _beforeFulfill(string[] calldata args) internal override {
require(args.length > 0, "Empty arguments array");
require(args[0].length > 0, "Empty house ID");
uint256 houseId = args[0].stringToUint();
require(houseId > 0, "Invalid house ID");
require(houseId <= MAX_HOUSE_ID, "House ID exceeds maximum");
lastHouseId = houseId;
}
function _processResponse(bytes memory response) internal override {
uint256 price = abi.decode(response, (uint256));
require(price > 0, "Invalid price");
require(price <= MAX_PRICE, "Price exceeds maximum");
require(price >= MIN_PRICE, "Price below minimum");
housePrices.setHousePrice(lastHouseId, price);
emit HousePriceUpdated(lastHouseId, price);
}

This mitigation adds comprehensive validation for:

  • Contract existence and validity

  • House ID format and range

  • Price value boundaries

  • Input array validation

The test results demonstrate that without these validations, the contract is vulnerable to invalid input attacks. Implementing the proposed mitigation will prevent these issues and ensure the security of the house price data.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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