<!-- canonical: https://0xsimao.com/findings/nftperp-i-size-isn-updated-properly -->

# Total Position Size isn't updated properly

Low/Info · Three Sigma · NFT perpetuals · 2nd January, 2024

Finding 3S-NFTPerp-L07 of the Nftperp Exchange security review.

- Report: /reports/nftperp-i
- Source: https://cdn.sanity.io/files/qoqld077/production/c19530de75e234ad15694b4563edb1fc9d2a3fd8.pdf

---

### Description

The totalPositionSize mapping is used to hold the position information for an amm using
the TotalPositionSize struct, which has the following fields:
- int256 netPositionSize
- uint256 positionSizeLong
- uint256 positionSizeShort
This mapping is updated exclusively through function _updateTotalPositionSize(...) of
the [ClearingHouseBase](https://github.com/nftperp/NFTPerp-V2-Contracts/blob/1c16f2010a851ac23aec73822d55388901bbe5e7/src/ClearingHouseBase.sol#L127-L139) contract:

```solidity
function _updateTotalPositionSize(IAMM amm, int256 size, Side side) internal
{
    TotalPositionSize memory tps = totalPositionSize[amm];
    tps.netPositionSize += size;
    if (side == Side.LONG) {
        tps.positionSizeLong = size.abs() + tps.positionSizeLong;
    } else {
        tps.positionSizeShort = size.abs() + tps.positionSizeShort;
    }
    totalPositionSize[amm] = tps;
}
```

The issue in this function is that both tps.positionSizeLong and tps.positionSizeShort
are being updated with the absolute value of the size, resulting in values that are always
increasing and don't reflect the current size of all long/short positions. For example, if
someone opens a long position with a size of 1000 and then closes this position, the
netPositionSize will go back to zero (as it should) but the positionSizeLong will go to
2000 (1000 on creation and 1000 on closure).

### Recommendation

Change the _updateTotalPositionSize() function to increase/decrease the
tps.positionSizeLong/tps.positionSizeShort variables depending on whether the size
is positive or negative:

```solidity
if (side == Side.LONG) {
    tps.positionSizeLong = size > 0 ?
tps.positionSizeLong +
size.abs(): tps.positionSizeLong - size.abs();
} else {
tps.positionSizeShort = size < 0 ? tps.positionSizeShort +
size.abs(): tps.positionSizeShort - size.abs();
}
```

Tests for the totalPositionSize mapping should also be added.

### Status

Addressed in [#a3dc121](https://github.com/nftperp/NFTPerp-V2-Contracts/commit/a3dc12125277d7b3aca472698edcb466ee84b5e6)

---

Related findings:

- [Protected downside is not updated when `cds.getTotalCdsDepositedAmount() < downsideProtected`](https://0xsimao.com/findings/autonomint-protected-downside-updated-deposited): Autonomint
