DittoETH

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

Limit short record might not get created

Summary

Limit short record might not get created.

Vulnerability Details

In the ShortOrdersFacet#createLimitShort function, there is a miscalculation while verifying if the user has enough collateral.

function createLimitShort(
...
if (s.vaultUser[Asset.vault][msg.sender].ethEscrowed < p.eth.mul(cr)) {
...
}

Users with valid collateral may be prevented from creating "limit short" orders. This is because the system expects them to have more collateral than necessary.

Impact

As p.eth.mul(cr) is a larger amount compared to p.eth, valid limit short records would not be created as they fail to satisfy the if condition.

Tools Used

Manual

Recommendations

Adjust the ShortOrdersFacet#createLimitShort function

function createLimitShort(
address asset,
uint80 price,
uint88 ercAmount,
MTypes.OrderHint[] memory orderHintArray,
uint16[] memory shortHintArray,
uint16 initialCR
) external isNotFrozen(asset) onlyValidAsset(asset) nonReentrant {
MTypes.CreateLimitShortParam memory p;
STypes.Asset storage Asset = s.asset[asset];
uint256 cr = LibOrders.convertCR(initialCR);
if (Asset.initialMargin > initialCR || cr >= Constants.CRATIO_MAX) {
revert Errors.InvalidInitialCR();
}
p.eth = price.mul(ercAmount);
p.minAskEth = LibAsset.minAskEth(asset);
p.minShortErc = LibAsset.minShortErc(asset);
if (ercAmount < p.minShortErc || p.eth < p.minAskEth) {
revert Errors.OrderUnderMinimumSize();
}
// For a short, need enough collateral to cover minting ERC (calculated using initialMargin)-
- if (s.vaultUser[Asset.vault][msg.sender].ethEscrowed < p.eth.mul(cr)) {
+ if (s.vaultUser[Asset.vault][msg.sender].ethEscrowed < p.eth) {
revert Errors.InsufficientETHEscrowed();
}
STypes.Order memory incomingShort;
incomingShort.addr = msg.sender;
incomingShort.price = price;
incomingShort.ercAmount = ercAmount;
incomingShort.id = Asset.orderId;
incomingShort.orderType = O.LimitShort;
incomingShort.creationTime = LibOrders.getOffsetTime();
incomingShort.initialMargin = initialCR; // 500 -> 5x
p.startingId = s.bids[asset][Constants.HEAD].nextId;
STypes.Order storage highestBid = s.bids[asset][p.startingId];
//@dev if match and match price is gt .5% to saved oracle in either direction, update startingShortId
if (highestBid.price >= incomingShort.price && highestBid.orderType == O.LimitBid)
{
LibOrders.updateOracleAndStartingShortViaThreshold(
asset, LibOracle.getPrice(asset), incomingShort, shortHintArray
);
}
p.oraclePrice = LibOracle.getSavedOrSpotOraclePrice(asset);
//@dev reading spot oracle price
if (incomingShort.price < p.oraclePrice) {
LibOrders.addShort(asset, incomingShort, orderHintArray);
} else {
LibOrders.sellMatchAlgo(asset, incomingShort, orderHintArray, p.minAskEth);
}
emit Events.CreateShort(
asset, msg.sender, incomingShort.id, incomingShort.creationTime
);
}

This change ensures that the user's escrowed amount is compared correctly with the required 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

Support

FAQs

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