DittoETH

Ditto
DeFiFoundryOracle
55,000 USDC
View results
Submission Details
Severity: medium
Valid

Oracle price not updated in `decreaseCollateral` function

Summary

The decreaseCollateral function does not update the oracle price as it's stated in the docs, this could lead to wrong cRatio being calculated and thus cause short undercollateralization after collateral decrease resulting in losses for the user and/or protocol.

Vulnerability Details

The issue occurs in the decreaseCollateral function below :

function decreaseCollateral(
address asset,
uint8 id,
uint88 amount
)
external
isNotFrozen(asset)
nonReentrant
onlyValidShortRecord(asset, msg.sender, id)
{
STypes.ShortRecord storage short = s.shortRecords[asset][msg.sender][
id
];
short.updateErcDebt(asset);
if (amount > short.collateral) revert Errors.InsufficientCollateral();
short.collateral -= amount;
//@audit oracle price not updated as said in docs meaning getCollateralRatio will use old price
uint256 cRatio = short.getCollateralRatio(asset);
if (cRatio < LibAsset.initialMargin(asset)) {
revert Errors.CollateralLowerThanMin();
}
uint256 vault = s.asset[asset].vault;
s.vaultUser[vault][msg.sender].ethEscrowed += amount;
LibShortRecord.disburseCollateral(
asset,
msg.sender,
amount,
short.zethYieldRate,
short.updatedAt
);
emit Events.DecreaseCollateral(asset, msg.sender, id, amount);
}

As you can see the function calls immediately getCollateralRatio to get the short collateral ration, this function uses the previously saved oracle price in its calculation :

function getCollateralRatio(
STypes.ShortRecord memory short,
address asset
) internal view returns (uint256 cRatio) {
//@audit using old price saved with getPrice
return
short.collateral.div(short.ercDebt.mul(LibOracle.getPrice(asset)));
}

The protocol docs about the oracles does state that the oracle price should be updated if decreaseCollateral is called and it's 15 min past the saved oracle time, you can check here.

Because the price is not updated before decreasing a short collateral amount, it can result in the following :

  • A short becoming undercollateralized if the asset price have dropped quickly compared to old saved price (which can happen in highly volatile market), this will lead for sure to losses for the protocol or the short holder.

  • The short holder may not be allowed to decrease the collateral amount because the saved price is below the current one.

Impact

Short becoming undercollateralized after collateral decrease with decreaseCollateral resulting in potential losses for the user and/or protocol.

Tools Used

Manual review

Recommended Mitigation

Use both getSavedOrSpotOraclePrice and getCollateralRatioSpotPrice to ensure that the collateral ratio is calculated with the correct price, the following modification should be made to the decreaseCollateral function :

function decreaseCollateral(
address asset,
uint8 id,
uint88 amount
)
external
isNotFrozen(asset)
nonReentrant
onlyValidShortRecord(asset, msg.sender, id)
{
STypes.ShortRecord storage short = s.shortRecords[asset][msg.sender][
id
];
short.updateErcDebt(asset);
if (amount > short.collateral) revert Errors.InsufficientCollateral();
short.collateral -= amount;
//@audit will use updated price if 15min has passed
uint256 oraclePrice = LibOracle.getSavedOrSpotOraclePrice(asset);
uint256 cRatio = short.getCollateralRatioSpotPrice(asset, oraclePrice);
if (cRatio < LibAsset.initialMargin(asset)) {
revert Errors.CollateralLowerThanMin();
}
uint256 vault = s.asset[asset].vault;
s.vaultUser[vault][msg.sender].ethEscrowed += amount;
LibShortRecord.disburseCollateral(
asset,
msg.sender,
amount,
short.zethYieldRate,
short.updatedAt
);
emit Events.DecreaseCollateral(asset, msg.sender, id, amount);
}
Updates

Lead Judging Commences

0xnevi Lead Judge
almost 2 years ago
0xnevi Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Other
0xnevi Lead Judge
almost 2 years ago
0xnevi Lead Judge almost 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-567

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.