DeFiLayer 1Layer 2
14,723 OP
View results
Submission Details
Severity: high
Invalid

Reentrancy vulnerability in `_updatePrice()` due to unchecled external calls.

Summary

A reentrancy vulnerability exists in the _updatePrice() function due to an unchecked external call to the SCRVUSD_ORACLE.update_price() function. If the oracle is malicious or compromised, it could re-enter the contract and manipulate verification logic.

Vulnerability Details

Reentrancy Risk in Oracle Call

Description:

The function _updatePrice() directly calls update_price() on SCRVUSD_ORACLE, which is an external contract. If this oracle allows reentrant calls, it could call back into the contract before execution is complete, leading to unexpected state changes or data manipulation.

function _updatePrice(
uint256[PARAM_CNT] memory params,
uint256 ts,
uint256 number
) internal returns (uint256) {
return IScrvusdOracle(SCRVUSD_ORACLE).update_price(params, ts, number);
}

=>No checks are performed before or after calling update_price().
=>If the oracle calls back into this contract, it may disrupt price verification logic.

Impact

=>Data Integrity Risk: The oracle could exploit reentrancy to manipulate price updates.
=>Unexpected State Changes: If verification functions rely on a compromised oracle, the contract might process invalid or manipulated data.
=>Security Exploit Potential: A malicious oracle contract could trigger a reentrancy attack, leading to unexpected behavior.

Tools Used

=> manual review

Recommendations

Use Reentrancy Guard

Use OpenZeppelin’s ReentrancyGuard to prevent reentrant calls:

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract ScrvusdVerifierV1 is ReentrancyGuard {
function _updatePrice(
uint256[PARAM_CNT] memory params,
uint256 ts,
uint256 number
) internal nonReentrant returns (uint256) {
return IScrvusdOracle(SCRVUSD_ORACLE).update_price(params, ts, number);
}
}

=>The nonReentrant modifier blocks reentrant calls, making the contract safer.

Apply Checks-Effects-Interactions Pattern

Modify _updatePrice() to update state first before calling an external contract:

function _updatePrice(
uint256[PARAM_CNT] memory params,
uint256 ts,
uint256 number
) internal returns (uint256 price) {
uint256 safeTimestamp = ts; // Store before external call
price = IScrvusdOracle(SCRVUSD_ORACLE).update_price(params, safeTimestamp, number);
}
Updates

Lead Judging Commences

0xnevi Lead Judge
6 months ago
0xnevi Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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