User may not be able to close position to realize their profit due to minimum trade size limit.
The minimum trade size can be updated by the admin, so the following scenario may happen:
To close the position, user would be forced to increase the position size and then they can close the position, however, this is unfair to the user, and the operation can also be risky.
function testAudit_UserCanNotClosePosition() public {
(
string memory name,
string memory symbol,
uint128 initialMarginRateX18,
uint128 maintenanceMarginRateX18,
uint128 maxOpenInterest,
uint128 maxSkew,
uint128 minTradeSizeX18,
uint256 skewScale,
OrderFees.Data memory orderFees
) = perpsEngine.getPerpMarketConfiguration(ETH_USD_MARKET_ID);
address alice = makeAddr("Alice");
uint256 depositAmount = 100e6;
deal(address(usdc), alice, depositAmount);
vm.startPrank(alice);
usdc.approve(address(perpsEngine), depositAmount);
uint128 tradingAccountId = createAccountAndDeposit(depositAmount, address(usdc));
perpsEngine.createMarketOrder(
OrderBranch.CreateMarketOrderParams({
tradingAccountId: tradingAccountId,
marketId: ETH_USD_MARKET_ID,
sizeDelta: int128(minTradeSizeX18)
})
);
vm.stopPrank();
vm.prank(marketOrderKeepers[ETH_USD_MARKET_ID]);
bytes memory mockSignedReport = getMockedSignedReport(ETH_USD_STREAM_ID, MOCK_ETH_USD_PRICE);
perpsEngine.fillMarketOrder(tradingAccountId, ETH_USD_MARKET_ID, mockSignedReport);
changePrank({ msgSender: users.owner.account });
GlobalConfigurationBranch.UpdatePerpMarketConfigurationParams memory params = GlobalConfigurationBranch
.UpdatePerpMarketConfigurationParams({
name: name,
symbol: symbol,
priceAdapter: address(new MockPriceFeed(18, int256(MOCK_ETH_USD_PRICE))),
initialMarginRateX18: initialMarginRateX18,
maintenanceMarginRateX18: maintenanceMarginRateX18,
maxOpenInterest: maxOpenInterest,
maxSkew: maxSkew,
maxFundingVelocity: ETH_USD_MAX_FUNDING_VELOCITY,
minTradeSizeX18: minTradeSizeX18 * 2,
skewScale: skewScale,
orderFees: orderFees,
priceFeedHeartbeatSeconds: ETH_USD_PRICE_FEED_HEARTBEATS_SECONDS
});
perpsEngine.updatePerpMarketConfiguration(ETH_USD_MARKET_ID, params);
(Position.State memory positionState) = perpsEngine.getPositionState(tradingAccountId, ETH_USD_MARKET_ID, MOCK_ETH_USD_PRICE * 2);
assertEq(50000000125000000000, positionState.unrealizedPnlUsdX18.unwrap());
changePrank({ msgSender: alice });
vm.expectRevert({ revertData: abi.encodeWithSelector(Errors.TradeSizeTooSmall.selector) });
perpsEngine.createMarketOrder(
OrderBranch.CreateMarketOrderParams({
tradingAccountId: tradingAccountId,
marketId: ETH_USD_MARKET_ID,
sizeDelta: int128(positionState.sizeX18.unwrap())
})
);
}
User can not close position to realize their profit without taking more risk and increasing the position size.
User should be allowed to close their position despite the trade size.