Core Contracts

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

The lendingPool can consume stale house NFT prices

Summary

The LendingPool doesn't check how old the NFTId price is.
The borrower can borrow against a stale colateral price or be liquidated unfairly.

Vulnerability Details

The admin can interogate the offchain price of a house NFTId by calling [BaseChainlinkFunctionsOracle::sendRequest]. When Chainlink process the request the token price is updated and the timestamp of the last price update is stored.

LendingPool::getNftPrice calls the RAACHousePrices::getLatestPrice to retrieve these informations.

function getNFTPrice(uint256 tokenId) public view returns (uint256) {
@> (uint256 price, uint256 lastUpdateTimestamp) = priceOracle.getLatestPrice(tokenId);
if (price == 0) revert InvalidNFTPrice();
return price;
}

The getLatestPrice function doesn't return the latest offchain price. Instead, it returns the price stored when the offchain price was requested and successfully fulfilled by Chainlink Functions.

The stored price returned by the getLatestPrice may be stale due to the following reasons :

  • the price wasn't requested in the last X days;

  • the request wasn't successfully fulfilled by Chainlink Functions last time when it was requested

When Chainlink Functions returns an error the old price is considered valid.
fulfillRequest doesn't handle the errors.

function fulfillRequest(
bytes32 requestId,
bytes memory response,
bytes memory err
) internal override {
s_lastResponse = response;
s_lastError = err;
@> if (err.length == 0) {// @audit error case is not handled;
if (response.length == 0) {
revert FulfillmentFailed();
}
_processResponse(response);
}
}

Impact

Borrowers may be liquidated unfairly.
Borrowers may borrow more than the collateral value.

Tools Used

Recommendations

A more robust price querying and price handling is required.
Consider the following changes:

  • in getNftPrice if the last price update is older than a predefined X days, revert

  • update the fulfillRequest to handle ChainlinkFunctions errors. The old stored price should not be considered valid.

  • consider implementing a new permissionless function to allow users to requesting the offchain price OR consider to automate Chainlink Functions.

Updates

Lead Judging Commences

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

LendingPool::getNFTPrice or getPrimeRate doesn't validate timestamp staleness despite claiming to, allowing users to exploit outdated collateral values during price drops

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

LendingPool::getNFTPrice or getPrimeRate doesn't validate timestamp staleness despite claiming to, allowing users to exploit outdated collateral values during price drops

Support

FAQs

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