Skip to content

Latest commit

 

History

History
111 lines (95 loc) · 4.7 KB

033.md

File metadata and controls

111 lines (95 loc) · 4.7 KB

Low Tangerine Cod

High

Whenever the current chain doesn't have USDA tokens, the downside will not be enforced correctly.

Summary

_getDownsideFromCDS forgets to update current chain downside value

Root Cause

Whenever borrower withdraw his position there is a check for the price of eth drops. Protocol implements protection for his usda stablecoins - downsideProtected:

-->         uint128 downsideProtected = calculateDownsideProtected(
                depositDetail.depositedAmountInETH,
                params.ethPrice,
                depositDetail.ethPriceAtDeposit
            );
            
           ...
    function calculateDownsideProtected(
        uint128 amount,
        uint128 currentEthPrice,
        uint128 depositEthPrice
    ) public pure returns (uint128) {
        if (currentEthPrice < depositEthPrice) {
-->            return (amount * (depositEthPrice - currentEthPrice)) / (100 * USDA_PRECISION);
        } else {
            return 0;
        }
    }           

Blockchian/contracts/lib/BorrowLib.sol#L826

This variable passed down to the function _getDownsideFromCDS:

    function _getDownsideFromCDS(
        uint128 downsideProtected,
        uint256 feeForOFT
    ) internal {
        if (cds.getTotalCdsDepositedAmount() < downsideProtected) {
            // Call the oftOrCollateralReceiveFromOtherChains function in global variables
            globalVariables.oftOrCollateralReceiveFromOtherChains{value: feeForOFT}(
                IGlobalVariables.FunctionToDo(3),
                IGlobalVariables.USDaOftTransferData(address(treasury),downsideProtected - cds.getTotalCdsDepositedAmount()),
                // Since we don't need ETH, we have passed zero params
                IGlobalVariables.CollateralTokenTransferData(address(0),0,0,0),
                IGlobalVariables.CallingFunction.BORROW_WITHDRAW,
                msg.sender
            );
        } else {
            // updating downside protected from this chain in CDS
            cds.updateDownsideProtected(downsideProtected);
        }
        // Burn the borrow amount
        treasury.approveTokens(IBorrowing.AssetName.USDa, address(this), downsideProtected);
        bool success = usda.contractBurnFrom(address(treasury), downsideProtected);
        if (!success) revert Borrow_BurnFailed();
    }

Blockchian/contracts/Core_logic/borrowing.sol#L725 After either if or else amount of getTotalCdsDepositedAmount and getTotalCdsDepositedAmountWithOptionFees from both chains should decrease by downsideProtected. Which is exacrtly happening in else statement but not in if - only downsideProtected - cds.getTotalCdsDepositedAmount()

Internal pre-conditions

No response

External pre-conditions

  1. Price of eth drops - which always happens from time to time.
  2. current chain doesn't have enough usda deposits.

Attack Path

No response

Impact

Cumalative rate will be broken, liquidation will be broken due to the fact that its depends on getTotalCdsDepositedAmount() The whole point of protocol is to protect protocol borrowers on price drops via cds holders which leads depegging of usda as of my understanding

PoC

No response

Mitigation

update

    function _getDownsideFromCDS(
        uint128 downsideProtected,
        uint256 feeForOFT
    ) internal {
        if (cds.getTotalCdsDepositedAmount() < downsideProtected) {
            // Call the oftOrCollateralReceiveFromOtherChains function in global variables
            globalVariables.oftOrCollateralReceiveFromOtherChains{value: feeForOFT}(
                IGlobalVariables.FunctionToDo(3),
                IGlobalVariables.USDaOftTransferData(address(treasury),downsideProtected - cds.getTotalCdsDepositedAmount()),
                // Since we don't need ETH, we have passed zero params
                IGlobalVariables.CollateralTokenTransferData(address(0),0,0,0),
                IGlobalVariables.CallingFunction.BORROW_WITHDRAW,
                msg.sender
            );
+            cds.updateDownsideProtected(cds.getTotalCdsDepositedAmount());
        } else {
            // updating downside protected from this chain in CDS
            cds.updateDownsideProtected(downsideProtected);
        }
        // Burn the borrow amount
        treasury.approveTokens(IBorrowing.AssetName.USDa, address(this), downsideProtected);
        bool success = usda.contractBurnFrom(address(treasury), downsideProtected);
        if (!success) revert Borrow_BurnFailed();
    }