Limit short record might not get created.
In the ShortOrdersFacet#createLimitShort function, there is a miscalculation while verifying if the user has enough collateral.
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.
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.
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.