`MagicLp.buyShares()`: a malicious actor can mint himself the `totalSupply` of the shares token with dust amounts if the reserves are empty
Audit: 2024-03-abracadabra-money-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-03-abracadabra-money/blob/1f4693fdbf33e9ad28132643e2d6f7635834c6c6/src/mimswap/MagicLP.sol#L360-L410


# Vulnerability details

## Impact

- The owner of the `MagicLp` contract can reset the reserves and target values of the base and quote tokens via `setParameters()`, where the owner can totally reset these value to zeros if the quote and base balances are emptied (transferred to an address determined by the owner):

  ```javascript
  function setParameters(
          address assetTo,
          uint256 newLpFeeRate,
          uint256 newI,
          uint256 newK,
          uint256 baseOutAmount,
          uint256 quoteOutAmount,
          uint256 minBaseReserve,
          uint256 minQuoteReserve
      ) public nonReentrant onlyImplementationOwner {

          // some code...

          _transferBaseOut(assetTo, baseOutAmount);
          _transferQuoteOut(assetTo, quoteOutAmount);
          (uint256 newBaseBalance, uint256 newQuoteBalance) = _resetTargetAndReserve(); //<< @audit :this function resets the reserves and targets to be equal to the base and quote balances of the contract
          emit ParametersChanged(newLpFeeRate, newI, newK, newBaseBalance, newQuoteBalance);
      }
  ```

  ```javascript
  function _resetTargetAndReserve() internal returns (uint256 baseBalance, uint256 quoteBalance) {
          baseBalance = _BASE_TOKEN_.balanceOf(address(this));
          quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this));

          if (baseBalance > type(uint112).max || quoteBalance > type(uint112).max) {
              revert ErrOverflow();
          }

          _BASE_RESERVE_ = uint112(baseBalance);
          _QUOTE_RESERVE_ = uint112(quoteBalance);
          _BASE_TARGET_ = uint112(baseBalance);
          _QUOTE_TARGET_ = uint112(quoteBalance);
          _RState_ = uint32(PMMPricing.RState.ONE);

          _twapUpdate();
      }
  ```

- So as can be noticed, the reserves and targets could be zeros (knowing that the minimum reserves checks are made before updating the reserves, while this should be done after `_resetTargetAndReserve()`), but how this could be exploited by a malicious user? let's see the following scenario:

  1. The owner empties the reserves (`_QUOTE_RESERVE_` & `_QUOTE_RESERVE_` are zeros).
  2. A malicious user directly transfers **1 wei** of quote token and **1 wei** of base token, and calls `sync()` function to set the reserves values to **1 wei**:

  ```javascript
      function _sync() internal {
          uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this));
          uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this));
          if (baseBalance != _BASE_RESERVE_) {
              _BASE_RESERVE_ = baseBalance.toUint112();
          }
          if (quoteBalance != _QUOTE_RESERVE_) {
              _QUOTE_RESERVE_ = quoteBalance.toUint112();
          }

          _twapUpdate();
      }
  ```

  3. Then this malicious user transfers another **2 wei*