Skip to content

Latest commit

 

History

History
73 lines (60 loc) · 4.73 KB

063.md

File metadata and controls

73 lines (60 loc) · 4.73 KB

Powerful Honeysuckle Anteater

High

No oracle for wrsEth exists on Mode L2 Network

Summary

For the Mode L2 network, the protocol uses Redstone Oracle. However, Redstone Oracle currently does not have a wrsEth asset feed on Mode L2.

Root Cause

In the MasterPriceOracle, we are supposed to set up addresses for the oracle feeds. However, a feed for wrsEth on Mode L2 by Redstone Oracle does not exist. Despite this, wrsEth is allowed as collateral, and using an inaccurate oracle exchange rate could lead to an insolvent protocol.

Reference from readme:

If you are integrating tokens, are you allowing only whitelisted tokens to work with the codebase or any complying with the standard? Are they assumed to have certain properties, e.g. be non-reentrant? Are there any types of weird tokens you want to integrate?

We are allowing only whitelisted tokens like wrsEth, weETH, ETH and USDa(Our own token) in borrowing contracts. And in dCDS we are allowing tokens like USDa(Our own token), USDT and Abond(Our own token) for redeeming.

Reference MasterPriceOracle.sol#L67-L68

 function _price(address underlying) internal view returns (uint128, uint128) {
        if (oracles[underlying] == address(0)) {
            revert("Price oracle not found for this underlying token address.");
        }

        if (block.chainid == 31337 || block.chainid == 34443) {
            IRedstoneOracle oracle = IRedstoneOracle(oracles[underlying]);
            // updating the underlying to address supported by redstone, based on underlying type
            if (underlying == assetAddress[IBorrowing.AssetName.WeETH]) {
                underlying = 0x028227c4dd1e5419d11Bb6fa6e661920c519D4F5;
@>>       } else if (underlying == assetAddress[IBorrowing.AssetName.WrsETH]) {
 //@audit-issue the wrapped version does not exist on Mode L2 network
@>>             underlying = 0x4186BFC76E2E237523CBC30FD220FE055156b41F;
            } else if (underlying == assetAddress[IBorrowing.AssetName.ETH]) {
                underlying = address(0);
            }
            uint256 priceInUsd = oracle.priceOf(underlying);
            uint256 priceOfNativeInUsd = oracle.priceOfETH();
            return (uint128((priceInUsd * 1e18) / priceOfNativeInUsd), uint128(priceOfNativeInUsd / 1e16));
        } else if (block.chainid == 10) {
 ......
    }

Query for the feed on Redstone Oracle: https://app.redstone.finance/app/feeds/?search=wrsETH&page=1&sortBy=popularity&sortDesc=false&perPage=32

This is a problem, as we can currently use wrsETH for collateral when borrowing, but, as mentioned, there isn't such a feed. So, when we go into the underlying = 0x4186BFC76E2E237523CBC30FD220FE055156b41F; case, we are essentially setting the rsETH feed, as 0x4186BFC76E2E237523CBC30FD220FE055156b41F is what this address corresponds to. However, we specify the IBorrowing.AssetName.WrsETH borrowing asset, not the rsETH one.

Impact

On Redstone Oracle, we only have the rsETH feed. However, the price would be inaccurate if we use it, as the prices of rsETH and wrsETH can differ by a few percent:

This discrepancy would result in inaccurate calculations for the LTV and may cause the protocol to believe it has more or fewer resources than it actually does. This could also lead to users withdrawing more than the protocol can afford, potentially making it insolvent, depending on whether rsETH or wrsETH has the higher price.

We use the exchange rate when calling the deposit function in the borrowing feature, which will be incorrect in this case, as we use the rsETH exchange rate instead of the wrsETH exchange rate when depositing wrsETH.

    function deposit(
        IBorrowing.BorrowLibDeposit_Params memory libParams,
        IBorrowing.BorrowDepositParams memory params,
        IBorrowing.Interfaces memory interfaces,
        mapping(IBorrowing.AssetName => address assetAddress) storage assetAddress
    ) public returns (uint256) {
        uint256 depositingAmount = params.depositingAmount;
        // Check the deposting amount is non zero
        if (params.depositingAmount == 0) revert IBorrowing.Borrow_NeedsMoreThanZero();

        // Calculate the depsoting amount in ETH
@>>     params.depositingAmount = (libParams.exchangeRate * params.depositingAmount) / 1 ether;

Mitigation

Consider only allowing rsETH as a deposit for collateral and adapt the code logic for that/use another oracle that offers wrsETH feed.