Skip to content

Latest commit

 

History

History
87 lines (65 loc) · 4.84 KB

007.md

File metadata and controls

87 lines (65 loc) · 4.84 KB

Low Tangerine Cod

High

the protocol will lose collateral from liquidation

Summary

omniChainData.totalAvailableLiquidationAmount doesn\t updates on user withdrawal

Root Cause

Whenever user deposits, totalAvailableLiquidationAmount being updated for omnichain. This is a number that will be used for liquidations from cds holders

        if (params.liquidate) {
            cdsDepositDetails.liquidationindex = omniChainData.noOfLiquidations;
            cdsDepositDetails.liquidationAmount = params.liquidationAmount;
            cdsDepositDetails.initialLiquidationAmount = params.liquidationAmount;
            params.totalAvailableLiquidationAmount += params.liquidationAmount;

            // updating global data
->          omniChainData.totalAvailableLiquidationAmount += params.liquidationAmount;
        }

Blockchian/contracts/lib/CDSLib.sol#L543 but its not happening on withdrawal. Why is it important to update it? Liquidation depends on this params, and every liquidations that will happen will think there are more tokens than suppose to. That means some positions will be liquidated when they are not suppose to

        require(omniChainData.totalAvailableLiquidationAmount >= liquidationAmountNeeded, "Don't have enough USDa in CDS to liquidate");

contracts/Core_logic/borrowLiquidation.sol#L216

There are other locations of code where this variable is being used, when distribute rewards, cds holders will receive less rewards than they deserve, their rewards proportional to total available for liquidation which is not tracked properly. share = user's liquidation amount / omniChainData.totalAvailableLiquidationAmount

                for (uint128 i = (liquidationIndexAtDeposit + 1); i <= params.omniChainData.noOfLiquidations; i++) {
                    uint128 liquidationAmount = params.cdsDepositDetails.liquidationAmount;
                    // If the user available liquidation is non zero
                    if (liquidationAmount > 0) {
                        CDSInterface.LiquidationInfo memory liquidationData = omniChainCDSLiqIndexToInfo[i];
                        // Calculate the share by taking ratio between
                        // User's available liquidation amount and total available liquidation amount
-->                        uint128 share = (liquidationAmount * 1e10) / uint128(liquidationData.availableLiquidationAmount);
                        // Update users available liquidation amount
                        params.cdsDepositDetails.liquidationAmount -= getUserShare(liquidationData.liquidationAmount, share);
                        // Based on the collateral type calculate the liquidated collateral to give to user
                        if (liquidationData.assetName == IBorrowing.AssetName.ETH) {
                            // increment eth amount
                            params.ethAmount += getUserShare(liquidationData.collateralAmount, share);
                        } else if (liquidationData.assetName == IBorrowing.AssetName.WeETH) {

Internal pre-conditions

External pre-conditions

Attack Path

There is withdrawTimeLimit on deposit/withdraw on cds,but it doesn't matter. Attacker can still deposit/withdraw to make liquidation non profitable to anyone by increasing omniChainData.totalAvailableLiquidationAmount thus increasing liquidationData.availableLiquidationAmount and allocate liquiadtion collateral to nonexistent users

Users will come and leave project by itself

Impact

An attacker can manipulate the protocol to cause a loss of liquidation collateral. Liquidations will not work. It will happen by itself as well since users will come and go - deposit/withdraw -> increasing totalAvailableLiquidationAmount

PoC

No response

Mitigation

update omniChainData.totalAvailableLiquidationAmount on cds withdrawal

                uint256 returnAmountWithGains = params.returnAmount + params.cdsDepositDetails.liquidationAmount;
                returnAmountWithGains -= params.cdsDepositDetails.initialLiquidationAmount;
+                omniChainData.totalAvailableLiquidationAmount -= params.cdsDepositDetails.depositedAmount - (params.cdsDepositDetails.initialLiquidationAmount - params.cdsDepositDetails.liquidationAmount) 
                // Calculate the yields which is accured between liquidation and now
                interfaces.treasury.updateYieldsFromLiquidatedLrts(
                    weETHAmount - ((weETHAmountInETHValue * 1 ether) /  params.weETH_ExchangeRate) + 
                    rsETHAmount - ((rsETHAmountInETHValue * 1 ether) /  params.rsETH_ExchangeRate)
                );