code4rena-2024-03-dittoeth-h03

[H-03] Users can mint DUSD with less collateral than required, which gives them free DUSD and may open a liquidatable position

보고서

Summary

부분 매칭 상태의 숏 주문을 취소할 때, 매칭된 양이 최소량보다 적다면 부족분을 유저의 담보를 사용해 추가 매칭한다. 필요한 담보의 양을 계산할 때 유저가 통제 가능한 값을 사용하므로, 이를 조작하면 적은 담보로 더 많은 dUSD를 발행할 수 있다.

Keyword

logic flaw, lack of input validation, defi

Vulnerability

유저가 숏 주문을 취소할 때, 부분 체결된 숏의 체결량이 최소량보다 적다면 모자란 만큼을 추가로 체결하고 남은 양은 취소한다. 너무 작은 양의 숏이 남아있지 않도록 하기 위해 체결된 숏의 최소 크기를 보장하기 위함이다. 숏 주문을 취소하면 숏 주문 생성시 맡긴 담보 토큰(dETH)을 돌려받는다. 최소량보다 모자란 만큼 체결할 때는 이 담보 토큰을 사용한다.

다음 코드는 최소량보다 모자란 만큼을 추가로 체결하는 로직이다. debtDiff 는 최소량보다 모자란 양으로, 이만큼의 dUSD를 더 체결해야 한다. debtDiff 에 상응하는 담보 dETH의 양 collateralDiff 를 계산하여 숏 체결에 사용한다. 이 collateralDiff를 계산할 때 2가지 문제가 있다.

  1. shortOrder.shortOrderCR 를 사용해 담보 양을 계산한다. 이 값은 숏터가 부담할 담보율을 의미하며 숏 주문 생성시 숏터가 지정하는 값이다. 만약 숏 주문의 담보 비율이 100% 가 아니라면 collateralDiffdebtDiff dUSD의 가치보다 작게 계산될 것이다. (shortOrderCR는 디폴트로 70% 이상으로 설정되어야 한다. shortOrderCR 가 70이라면 정상 거래 시 100%는 유저의 구매금, 70%는 숏터의 담보 총합 170% 가치의 dETH가 담보로 묶인다.)
  2. shortOrder.price 를 사용해 담보 양을 계산한다. 이 값은 숏터가 지정한 거래 가격이다. 만약 숏터가 실제보다 낮은 가격을 등록했다면 실제보다 적은 담보가 사용될 것이다.

즉, 최소량 부족분 자동 체결은 시세가 아닌 숏터가 제공한 값에 의존하여 이루어진다는 문제점이 있다.

    ...
@>  uint88 debtDiff = minShortErc - shortRecord.ercDebt;
    {
        STypes.Vault storage Vault = s.vault[vault];
 
@>      uint88 collateralDiff = shortOrder.price.mulU88(debtDiff).mulU88(LibOrders.convertCR(shortOrder.shortOrderCR));
 
        LibShortRecord.fillShortRecord(
            asset,
            shorter,
            shortRecordId,
            SR.FullyFilled,
            collateralDiff,
            debtDiff,
            Asset.ercDebtRate,
            Vault.dethYieldRate
        );
 
        Vault.dethCollateral += collateralDiff;
        Asset.dethCollateral += collateralDiff;
        Asset.ercDebt += debtDiff;
 
        // @dev update the eth refund amount
        eth -= collateralDiff;
    }
    // @dev virtually mint the increased debt
    s.assetUser[asset][shorter].ercEscrowed += debtDiff;
    ...

악성 유저는 다음과 같이 악용할 수 있다.

  1. shortOrderCR 를 100%보다 낮게 설정하여 숏 주문을 만든다.
  2. 해당 주문이 부분 매칭되도록 한다.
  3. 숏 주문을 취소하여 dUSD를 시세보다 저렴하게 민팅한다.

Impact

제공한 담보의 가치보다 많은 dUSD를 발행할 수 있다.

Mitigation

최소량 부족분 구매 시 오라클에서 가져온 현재 가격을 사용한다. shortOrder.shortOrderCR < initialCR 라면 initialCR 를 대신 사용한다. 이렇게 변경하면 기존에 맡겼던 dETH 담보가 모자라 숏 주문을 닫을 수 없는 상황이 생길 수 있다. 이를 대비하여 추가금을 받는 것을 고려하라.

Memo

유사한 이슈가 DittoETH의 다음 오딧에서도 다시 나타났다.


tags: bughunting, dittoeth, smart contract, solidity, logic flaw, lack-of-input-validation-vul, defi, severity high