Assessment reports>Avantis>High findings>Partial trades update open-interest incorrectly
Category: Coding Mistakes

Partial trades update open-interest incorrectly

High Severity
High Impact
High Likelihood

Description

The function registerPartialTrade is used by _unregisterTrade to register a partial trade in case the collateral to be withdrawn is less than the initial position of the trade. When this partial trade is registered, the open interest is updated using the function _updateOpenInterestUSDC in registerPartialTrade as shown below:

function registerPartialTrade(
    address trader,
    uint pairIndex,
    uint index,
    uint _amountReduced
) external override onlyTrading {
    Trade storage t = _openTrades[trader][pairIndex][index];
    TradeInfo storage i = _openTradesInfo[trader][pairIndex][index];
    if (t.leverage == 0) {
        return;
    }
    t.initialPosToken -= _amountReduced;
    i.openInterestUSDC -= _amountReduced.mul(t.leverage);
    _updateOpenInterestUSDC(trader, pairIndex, i.openInterestUSDC,
        false, t.buy, t.openPrice);
}

function _updateOpenInterestUSDC(
    address _trader,
    uint _pairIndex,
    uint _leveragedPosUSDC,
    bool _open,
    bool _long,
    uint _price
) private {
    uint index = _long ? 0 : 1;
    uint[2] storage o = openInterestUSDC[_pairIndex];

    // Fix beacuse of Dust during partial close
    if (!_open) _leveragedPosUSDC =
        _leveragedPosUSDC > o[index] ? o[index] : _leveragedPosUSDC;

    o[index] = _open ?
        o[index] + _leveragedPosUSDC : o[index] - _leveragedPosUSDC;
    totalOI = _open ?
        totalOI + _leveragedPosUSDC : totalOI - _leveragedPosUSDC;
    _walletOI[_trader] = _open ?
        _walletOI[_trader] + _leveragedPosUSDC :
        _walletOI[_trader] - _leveragedPosUSDC;

    emit OIUpdated(_open, _long, _pairIndex, _leveragedPosUSDC, _price);
}

Here, the amount of open interest to be reduced should be equal to _amountReduced.mul(t.leverage). But the argument passed to _updateOpenInterestUSDC is i.openInterestUSDC, which is the original open interest minus the new amount times leverage.

Impact

If the open interest is incorrectly updated, it would lead to incorrect returned values for the loss-protection tier, utilization multiplier, long multiplier, short multiplier, and rollover fees.

Recommendations

We recommend replacing i.openInterestUSDC with _amountReduced.mul(t.leverage) in the third parameter of the call to _updateOpenInterestUSDC.

Remediation

This issue has been acknowledged by Avantis Labs, Inc., and a fix was implemented in commit cfb288e3.

Zellic © 2025Back to top ↑