Could lead to a sandwich attack by a malicious user who has been unable to deposit collateral and is liquidated
function depositMargin(uint128 tradingAccountId, address collateralType, uint256 amount) public virtual {
...
TradingAccount.Data storage tradingAccount = TradingAccount.loadExisting(tradingAccountId);
UD60x18 amountX18 = marginCollateralConfiguration.convertTokenAmountToUd60x18(amount);
UD60x18 depositCapX18 = ud60x18(marginCollateralConfiguration.depositCap);
UD60x18 totalCollateralDepositedX18 = ud60x18(marginCollateralConfiguration.totalDeposited);
_requireAmountNotZero(amountX18);
@> _requireEnoughDepositCap(collateralType, amountX18, depositCapX18, totalCollateralDepositedX18);
Users who want to add collateral to avoid being liquidated, but due to the sandwich attack of the giant whale (no fees for depositing and withdrawing collateral), may not be able to do so all the time, leading to liquidation
function depositMargin(uint128 tradingAccountId, address collateralType, uint256 amount) public virtual {
// fetch storage slot for this collateral's config config
MarginCollateralConfiguration.Data storage marginCollateralConfiguration =
MarginCollateralConfiguration.load(collateralType);
// load existing trading account; reverts for non-existent account
// does not enforce msg.sender == account owner so anyone can deposit
// collateral for other traders if they wish
TradingAccount.Data storage tradingAccount = TradingAccount.loadExisting(tradingAccountId);
// convert uint256 -> UD60x18; scales input amount to 18 decimals
UD60x18 amountX18 = marginCollateralConfiguration.convertTokenAmountToUd60x18(amount);
// uint128 -> UD60x18
UD60x18 depositCapX18 = ud60x18(marginCollateralConfiguration.depositCap);
// uint256 -> UD60x18
UD60x18 totalCollateralDepositedX18 = ud60x18(marginCollateralConfiguration.totalDeposited);
// enforce converted amount > 0
_requireAmountNotZero(amountX18);
// enforce new deposit + already deposited <= deposit cap
- _requireEnoughDepositCap(collateralType, amountX18, depositCapX18, totalCollateralDepositedX18);
// enforce collateral has configured liquidation priority
_requireCollateralLiquidationPriorityDefined(collateralType);
// get the tokens first
IERC20(collateralType).safeTransferFrom(msg.sender, address(this), amount);
// then perform the actual deposit
tradingAccount.deposit(collateralType, amountX18);
+ // load new totalDeposited
+ UD60x18 totalCollateralDepositedX18 = ud60x18(marginCollateralConfiguration.totalDeposited);
+ if ( totalCollateralDepositedX18 > depositCapX18) {
+ (UD60x18 requiredInitialMarginUsdX18,, SD59x18 accountTotalUnrealizedPnlUsdX18) =
+ tradingAccount.getAccountMarginRequirementUsdAndUnrealizedPnlUsd(0, SD59x18_ZERO);
+ SD59x18 marginBalanceUsdX18 = tradingAccount.getMarginBalanceUsd(accountTotalUnrealizedPnlUsdX18);
+ require(marginBalanceUsdX18 <= requiredInitialMarginUsdX18," deposit cap");
+ }
emit LogDepositMargin(msg.sender, tradingAccountId, collateralType, amount);
}