function test_chackLiquidationReturn() public {
MarketConfig memory fuzzMarketConfig = getFuzzMarketConfig(DOGE_USD_MARKET_ID);
MockPriceFeed priceFeed = MockPriceFeed(fuzzMarketConfig.priceAdapter);
uint256 initialPrice = 1e16;
priceFeed.updateMockPrice(initialPrice);
deal({ token: address(usdc), to: users.naruto.account, give: 10_000_000e6 });
deal({ token: address(usdc), to: users.sasuke.account, give: 10_000_000e6 });
deal({ token: address(usdc), to: users.sakura.account, give: 10_000_000e6 });
deal({ token: address(usdc), to: users.madara.account, give: 10_000_000e6 });
changePrank({ msgSender: users.naruto.account });
uint128 tradingAccountId = createAccountAndDeposit(10_000_000e6, address(usdc));
changePrank({ msgSender: users.sasuke.account });
uint128 sasukeAccountId = createAccountAndDeposit(10_000_000e6, address(usdc));
changePrank({ msgSender: users.sakura.account });
uint128 sakuraAccountId = createAccountAndDeposit(10_000_000e6, address(usdc));
changePrank({ msgSender: users.madara.account });
uint128 madaraAccountId = createAccountAndDeposit(10_000_000e6, address(usdc));
uint256 initialMarginRate = fuzzMarketConfig.imr;
uint256 marginValueUsd = 10_000e18;
changePrank({ msgSender: users.naruto.account });
openPosition(fuzzMarketConfig, tradingAccountId, initialMarginRate, marginValueUsd, true);
changePrank({ msgSender: users.sasuke.account });
openPosition(fuzzMarketConfig, sasukeAccountId, initialMarginRate, marginValueUsd, false);
changePrank({ msgSender: users.sakura.account });
openPosition(fuzzMarketConfig, sakuraAccountId, initialMarginRate, marginValueUsd, true);
changePrank({ msgSender: users.madara.account });
openPosition(fuzzMarketConfig, madaraAccountId, initialMarginRate, marginValueUsd, false);
uint128[] memory liquidatableAccountsIds = perpsEngine.checkLiquidatableAccounts(0, 4);
assertEq(liquidatableAccountsIds.length, 4);
}
It does not lead to any direct security risks or unintended state changes. However, it may result in inefficient gas usage when processing liquidations, as the LiquidationBranch::liquidateAccounts
function still iterates over zero values before skipping them.
It could also be source of potential confusion for integrators who may assume that the all the returned liquidatableAccountsIds
are accounts IDs that should be liquidated.
function checkLiquidatableAccounts(
uint256 lowerBound,
uint256 upperBound
)
external
view
returns (uint128[] memory liquidatableAccountsIds)
{
// Prepare output array size
liquidatableAccountsIds = new uint128[](upperBound - lowerBound);
+ uint256 validAccountsCount;
// ...
for (uint256 i = lowerBound; i < upperBound; i++) {
// ...
// Account can be liquidated if requiredMargin > marginBalance
if (TradingAccount.isLiquidatable(requiredMaintenanceMarginUsdX18, marginBalanceUsdX18)) {
- liquidatableAccountsIds[i] = tradingAccountId;
+ liquidatableAccountsIds[validAccountsCount++] = tradingAccountId;
}
}
+ // Resize the liquidatableAccountsIds array to the actual number of valid accounts
+ assembly {
+ mstore(liquidatableAccountsIds, validAccountsCount)
+ }
}