Closed c4-bot-3 closed 3 weeks ago
Protocol did a consistent price check on L2 i.e. if Price reported by Receiver is less than 1 ETH then revert. - https://github.com/Renzo-Protocol/Contracts/pull/96/files#diff-478c8300348d5b84e98f49d7cc8c761b1f45617cdbcb5ed3487dfc563a9aac8cR347. So this would invalidate this as price cannot be < 1 ETH on L2s.
Thanks @jatinj615. I believe this wasn't in the mitigation scope, so the finding would remain valid.
This issue is out-of-scope
. This issue (wrongly) describes the same root issue that has been extensively documented in our issue:
primary finding
:Adding
if (_scaledPrice < 1 ether) revert InvalidOraclePrice()
to xRenzoDeposit.sol
will not do anything because it can still be side-stepped by the L1 CCIP calls, as extensively described in the issues above.
The mitigation provided by the Sponsor is a fix for the issues provided above. Even though this mitigation is not in scope, findings submitted that are the same as findings with a sponsor acknowledged
label, are out of scope.
The mitigation provided by the Sponsor being in-scope
or out-of-scope
is irrelevant since this issue is out-of-scope
due to the fact that it's the same issue that has already been labelled as acknowledged
by the Sponsor.
Furthermore, this report is factually incorrect. The report claims being able to function without an oracle. This means it won't receive price updates from either L1 or L2, resorting to the admin manually updating the price by calling `updatePriceByOwner():
/**
* @notice Updates the price feed from the Owner account
* @dev Sets the last price and timestamp
* @param price price of ezETH to ETH - 18 decimal precision
*/
function updatePriceByOwner(uint256 price) external onlyOwner {
return _updatePrice(price, block.timestamp);
}
This might be hypothetically possible but no project would hire an engineer to manually update the price.
If the report was meant to describe the scenario where the Sponsor is only operating by receiving L1 CCIP calls to update the price feed, then that is correct, this is one of the configurations that is possible.
However, the issue described in this report, being able to side-step the (_scaledPrice < 1 ether)
has been already been described in our original issue:
Thanks!
alcueca marked the issue as unsatisfactory: Out of scope
Lines of code
https://github.com/Renzo-Protocol/Contracts/blob/7dabe5478ec6dbf084135737bb0d88960e80b63e/contracts/Bridge/L2/xRenzoDeposit.sol#L299
Vulnerability details
RenzoOracleL2 has a check implemented, meant to block xezETH mints on L2 whenever the price goes below
1e18
:This check however can be bypassed in
xRenzoDeposit
because this contract can also work without an oracle configured and with prices streamed from L1:It's worth noting that while prices are streamed by an authority in L1, these prices can't be controlled by this authority, and their source (BalancerRateProvider) does not have either a
price < 1e18
check:Impact
When operating without an oracle, xRenzoDeposit can mint at prices below
1e18
, bypassing the checks implemented in RenzoOracleL2.Proof of Concept
oracle == address(0)
Tools Used
Code review
Recommended Mitigation Steps
Consider adding a
price < 1e18
check also inxRenzoDeposit.getMintRate()
.Assessed type
Invalid Validation