# MaverickV2Pool

**Inherits:** [IMaverickV2Pool](https://docs.mav.xyz/technical-reference/maverick-v2/v2-contracts/maverick-v2-common-contracts/interfaces/imaverickv2pool), [IMaverickV2PoolAdmin](https://docs.mav.xyz/technical-reference/maverick-v2/v2-contracts/maverick-v2-common-contracts/interfaces/imaverickv2pooladmin)

Pool contract for Maverick V2. There is no pool owner, but the Factory contract does have the ability to set and collect protocol fees. Users can add liquidity, remove liquidity, swap, and migrate bins up the merge stack. User liquidity is allocated to a recipient and can be assigned, by the sender, to a "subaccount". But liquidity is not transferable. For liquidity transfer and other manipulation capabilities, use the v2-supplemental Position (ERC-721 interfaces) or BoostedPosition (ERC-20 interfaces) contracts.

This contract does not support rebasing tokens. However, there are limited protections built in for tokens that have a negative rebase. On negative rebase, the pool's internal accounting of its balances will diverge from the token balance accounting. In order to interact with swap or add liquidity after a negative rebase, a user will have first make the pool solvent by transfering the pool enough asset so the two accounting systmes match. Post negative rebase, users will be able to remove their pro rata balance from the pool. Any positive rebase of the pool's balance will be accrued to the next add or swap user. That is, the proceeds of a positive rebase will not be distributed to all LPs.

Tokens such as stETH that have a mismatch between the amount transfered and the balanceOf of a user post-transfer are not supported by this contract. Such a mismatch between transfer and balanceOf will result in a revert when attempting to add liquidity.

### State Variables <a href="#state-variables" id="state-variables"></a>

#### accessor <a href="#accessor" id="accessor"></a>

Address of Pool accessor. This is Zero address for permissionless pools.

```solidity
address public immutable accessor;
```

#### kinds <a href="#kinds" id="kinds"></a>

1-15 number to represent the active kinds. 0b0001 = static; 0b0010 = right; 0b0100 = left; 0b1000 = both; E.g. a pool with all 4 modes will have kinds = b1111 = 15

```solidity
uint8 public immutable kinds;
```

#### protocolFeeA <a href="#protocolfeea" id="protocolfeea"></a>

Accumulated tokenA protocol fee.

```solidity
uint128 public protocolFeeA;
```

#### protocolFeeB <a href="#protocolfeeb" id="protocolfeeb"></a>

Accumulated tokenB protocol fee.

```solidity
uint128 public protocolFeeB;
```

#### tickSpacing <a href="#tickspacing" id="tickspacing"></a>

TickSpacing of pool where 1.0001^tickSpacing is the bin width.

```solidity
uint256 public immutable tickSpacing;
```

#### tokenA <a href="#tokena" id="tokena"></a>

Pool tokenA. Address of tokenA is such that tokenA < tokenB.

```solidity
IERC20 public immutable tokenA;
```

#### tokenB <a href="#tokenb" id="tokenb"></a>

Pool tokenB.

```solidity
IERC20 public immutable tokenB;
```

#### lookback <a href="#lookback" id="lookback"></a>

Lookback period of pool in seconds.

```solidity
uint256 public immutable lookback;
```

#### factory <a href="#factory" id="factory"></a>

Deploying factory of the pool and also contract that has ability to set and collect protocol fees for the pool.

```solidity
IMaverickV2Factory public immutable factory;
```

#### tokenAScale <a href="#tokenascale" id="tokenascale"></a>

Most significant bit of scale value is a flag to indicate whether tokenA has more or less than 18 decimals. Scale is used in conjuction with Math.toScale/Math.fromScale functions to convert from token amounts to D18 scale internal pool accounting.

```solidity
uint256 public immutable tokenAScale;
```

#### tokenBScale <a href="#tokenbscale" id="tokenbscale"></a>

Most significant bit of scale value is a flag to indicate whether tokenA has more or less than 18 decimals. Scale is used in conjuction with Math.toScale/Math.fromScale functions to convert from token amounts to D18 scale internal pool accounting.

```solidity
uint256 public immutable tokenBScale;
```

#### lendingFeeRateD18 <a href="#lendingfeerated18" id="lendingfeerated18"></a>

```solidity
uint256 public lendingFeeRateD18;
```

#### bins <a href="#bins" id="bins"></a>

Mapping of Bin objects for the pool. Each Bin is indexed by an incrementing uint32 ID. There are at most 4 bins per tick. Bin state is viewable with getBin().

```solidity
mapping(uint32 => Bin.Instance) internal bins;
```

#### ticks <a href="#ticks" id="ticks"></a>

Mapping of Tick objects for the pool. There are at most 4 bins per tick. Ticks are indexed by their position in the log price domain. The number of ticks is limited by Constants.sol/MAX\_TICK. Tick state is viewable with getTick().

```solidity
mapping(int32 => TickState) internal ticks;
```

#### \_state <a href="#state" id="state"></a>

Dynamic state variables of the pool. Takes up two storage slots.

```solidity
State internal _state;
```

#### \_feeAIn <a href="#feeain" id="feeain"></a>

Fee rate for tokenA in swaps in 18-decimal format.

```solidity
uint256 internal immutable _feeAIn;
```

#### \_feeBIn <a href="#feebin" id="feebin"></a>

Fee rate for tokenB in swaps in 18-decimal format.

```solidity
uint256 internal immutable _feeBIn;
```

### Functions <a href="#functions" id="functions"></a>

#### constructor <a href="#constructor" id="constructor"></a>

Constructor is called by the deployer contract. In the constructor the pool calls back to the deployer to set the pool parameters.

```solidity
constructor();
```

#### addLiquidity <a href="#addliquidity" id="addliquidity"></a>

Add liquidity to a pool. This function allows users to deposit tokens into a liquidity pool.

This function will call `maverickV2AddLiquidityCallback` on the calling contract to collect the tokenA/tokenB payment.

```solidity
function addLiquidity(address recipient, uint256 subaccount, AddLiquidityParams calldata params, bytes calldata data)
    public
    virtual
    returns (uint256 tokenAAmount, uint256 tokenBAmount, uint32[] memory binIds);
```

**Parameters**

| Name         | Type                 | Description                                                                              |
| ------------ | -------------------- | ---------------------------------------------------------------------------------------- |
| `recipient`  | `address`            | The account that will receive credit for the added liquidity.                            |
| `subaccount` | `uint256`            | The account that will receive credit for the added liquidity.                            |
| `params`     | `AddLiquidityParams` | Parameters containing the details for adding liquidity, such as token types and amounts. |
| `data`       | `bytes`              | Bytes information that gets passed to the callback.                                      |

**Returns**

| Name           | Type       | Description                                        |
| -------------- | ---------- | -------------------------------------------------- |
| `tokenAAmount` | `uint256`  | The amount of token A added to the pool.           |
| `tokenBAmount` | `uint256`  | The amount of token B added to the pool.           |
| `binIds`       | `uint32[]` | An array of bin IDs where the liquidity is stored. |

#### migrateBinUpStack <a href="#migratebinupstack" id="migratebinupstack"></a>

Migrate bins up the linked list of merged bins so that its mergeId is the currrent active bin.

Liquidy can only be removed from a bin that is either unmerged or has a mergeId of an unmerged bin. If a bin is merged more than one level deep, it must be migrated up the merge stack to the root bin before liquidity removal.

```solidity
function migrateBinUpStack(uint32 binId, uint32 maxRecursion) public virtual;
```

**Parameters**

| Name           | Type     | Description                                    |
| -------------- | -------- | ---------------------------------------------- |
| `binId`        | `uint32` | The ID of the bin to migrate.                  |
| `maxRecursion` | `uint32` | The maximum recursion depth for the migration. |

#### removeLiquidity <a href="#removeliquidity" id="removeliquidity"></a>

Removes liquidity from the pool.

Liquidy can only be removed from a bin that is either unmerged or has a mergeId of an unmerged bin. If a bin is merged more than one level deep, it must be migrated up the merge stack to the root bin before liquidity removal.

```solidity
function removeLiquidity(address recipient, uint256 subaccount, RemoveLiquidityParams calldata params)
    public
    virtual
    returns (uint256 tokenAOut, uint256 tokenBOut);
```

**Parameters**

| Name         | Type                    | Description                            |
| ------------ | ----------------------- | -------------------------------------- |
| `recipient`  | `address`               | The address to receive the tokens.     |
| `subaccount` | `uint256`               | The subaccount for the recipient.      |
| `params`     | `RemoveLiquidityParams` | The parameters for removing liquidity. |

**Returns**

| Name        | Type      | Description                     |
| ----------- | --------- | ------------------------------- |
| `tokenAOut` | `uint256` | The amount of token A received. |
| `tokenBOut` | `uint256` | The amount of token B received. |

#### swap <a href="#swap" id="swap"></a>

Swap tokenA/tokenB assets in the pool. The swap user has two options for funding their swap.

* The user can push the input token amount to the pool before calling the swap function. In order to avoid having the pool call the callback, the user should pass a zero-length `data` bytes object with the swap call.
* The user can send the input token amount to the pool when the pool calls the `maverickV2SwapCallback` function on the calling contract. That callback has input parameters that specify the token address of the input token, the input and output amounts, and the bytes data sent to the swap function.

If the users elects to do a callback-based swap, the output assets will be sent before the callback is called, allowing the user to execute flash swaps. However, the pool does have reentrancy protection, so a swapper will not be able to interact with the same pool again while they are in the callback function.

```solidity
function swap(address recipient, SwapParams memory params, bytes calldata data)
    public
    virtual
    returns (uint256 amountIn, uint256 amountOut);
```

**Parameters**

| Name        | Type         | Description                                         |
| ----------- | ------------ | --------------------------------------------------- |
| `recipient` | `address`    | The address to receive the output tokens.           |
| `params`    | `SwapParams` | Parameters containing the details of the swap       |
| `data`      | `bytes`      | Bytes information that gets passed to the callback. |

#### setFee <a href="#setfee" id="setfee"></a>

Sets fee for permissioned pools. May only be called by the accessor.

```solidity
function setFee(uint256, uint256) public virtual;
```

#### flashLoan <a href="#flashloan" id="flashloan"></a>

Loan tokenA/tokenB assets from the pool to recipient. The fee rate of a loan is determined by `lendingFeeRateD18`, which is set at the protocol level by the factory. This function calls `maverickV2FlashLoanCallback` on the calling contract. At the end of the callback, the caller must pay back the loan with fee (if there is a fee).

```solidity
function flashLoan(address recipient, uint256 amountA, uint256 amountB, bytes calldata data)
    public
    virtual
    returns (uint128 lendingFeeA, uint128 lendingFeeB);
```

**Parameters**

| Name        | Type      | Description                                         |
| ----------- | --------- | --------------------------------------------------- |
| `recipient` | `address` | The address to receive the loaned tokens.           |
| `amountA`   | `uint256` |                                                     |
| `amountB`   | `uint256` | Loan amount of tokenA sent to recipient.            |
| `data`      | `bytes`   | Bytes information that gets passed to the callback. |

#### adminAction <a href="#adminaction" id="adminaction"></a>

Perform pool admin action; this function can only be called by the pool factory contract. When called by other callers, this function will revert.

```solidity
function adminAction(AdminAction action, uint256 value) external;
```

**Parameters**

| Name     | Type          | Description                                                                             |
| -------- | ------------- | --------------------------------------------------------------------------------------- |
| `action` | `AdminAction` | Selector of admin action from AdminAction enum.                                         |
| `value`  | `uint256`     | Applicable for "setting" admin actions and is the new value of the parameter being set. |

#### \_lockPool <a href="#lockpool" id="lockpool"></a>

Internal function to lock the pool.

```solidity
function _lockPool() internal returns (State memory currentState);
```

#### \_unlockPool <a href="#unlockpool" id="unlockpool"></a>

Internal function to unlock the pool.

```solidity
function _unlockPool() internal;
```

#### getState <a href="#getstate" id="getstate"></a>

External function to get the state of the pool.

```solidity
function getState() external view returns (State memory);
```

#### getCurrentTwa <a href="#getcurrenttwa" id="getcurrenttwa"></a>

External function to get the current time-weighted average price.

```solidity
function getCurrentTwa() external view returns (int256);
```

#### fee <a href="#fee" id="fee"></a>

Pool swap fee for the given direction (A-in or B-in swap) in 18-decimal format. E.g. 0.01e18 is a 1% swap fee.

```solidity
function fee(bool tokenAIn) public view virtual returns (uint256);
```

#### binIdByTickKind <a href="#binidbytickkind" id="binidbytickkind"></a>

ID of bin at input tick position and kind.

```solidity
function binIdByTickKind(int32 tick, uint256 kind) public view returns (uint32 binId);
```

#### getBin <a href="#getbin" id="getbin"></a>

Return state of Bin at input binId.

```solidity
function getBin(uint32 binId) external view returns (BinState memory bin);
```

#### getTick <a href="#gettick" id="gettick"></a>

Return state of Tick at input tick position.

```solidity
function getTick(int32 tick) external view returns (TickState memory _tick);
```

#### balanceOf <a href="#balanceof" id="balanceof"></a>

Retrieves the balance of a user within a bin.

```solidity
function balanceOf(address user, uint256 subaccount, uint32 binId) external view returns (uint128 lpBalance);
```

**Parameters**

| Name         | Type      | Description                  |
| ------------ | --------- | ---------------------------- |
| `user`       | `address` | The user's address.          |
| `subaccount` | `uint256` | The subaccount for the user. |
| `binId`      | `uint32`  | The ID of the bin.           |

#### \_kindSupportedByPool <a href="#kindsupportedbypool" id="kindsupportedbypool"></a>

Bool indicator of whether the input kind is supported by the pool.

```solidity
function _kindSupportedByPool(uint8 kind) internal view returns (bool);
```

#### \_tickSqrtPriceAndLiquidity <a href="#ticksqrtpriceandliquidity" id="ticksqrtpriceandliquidity"></a>

Retrieves the square root price and liquidity of a tick.

```solidity
function _tickSqrtPriceAndLiquidity(int32 tick)
    internal
    view
    returns (uint256 sqrtLowerTickPrice, uint256 sqrtUpperTickPrice, uint256 sqrtPrice, TickData memory output);
```

**Parameters**

| Name   | Type    | Description     |
| ------ | ------- | --------------- |
| `tick` | `int32` | The tick value. |

**Returns**

| Name                 | Type       | Description                              |
| -------------------- | ---------- | ---------------------------------------- |
| `sqrtLowerTickPrice` | `uint256`  | The square root of the lower tick price. |
| `sqrtUpperTickPrice` | `uint256`  | The square root of the upper tick price. |
| `sqrtPrice`          | `uint256`  | The square root price.                   |
| `output`             | `TickData` | The tick data.                           |

#### \_tokenBalance <a href="#tokenbalance" id="tokenbalance"></a>

Get the balance of a given token.

```solidity
function _tokenBalance(IERC20 token) internal view returns (uint128);
```

**Parameters**

| Name    | Type     | Description                               |
| ------- | -------- | ----------------------------------------- |
| `token` | `IERC20` | The IERC20 token to check the balance of. |

**Returns**

| Name     | Type      | Description               |
| -------- | --------- | ------------------------- |
| `<none>` | `uint128` | The balance of the token. |

#### \_checkTokenSolvency <a href="#checktokensolvency" id="checktokensolvency"></a>

```solidity
function _checkTokenSolvency(IERC20 token, uint256 internalBalance) internal view;
```

#### \_getOrCreateBin <a href="#getorcreatebin" id="getorcreatebin"></a>

Get or create a bin and return its ID and storage reference.

```solidity
function _getOrCreateBin(State memory currentState, uint8 kind, int32 tick)
    internal
    returns (uint32 binId, Bin.Instance storage bin);
```

**Parameters**

| Name           | Type    | Description                                         |
| -------------- | ------- | --------------------------------------------------- |
| `currentState` | `State` | The State struct containing the current state data. |
| `kind`         | `uint8` | The uint8 value representing the kind of bin.       |
| `tick`         | `int32` | The int32 value representing the tick.              |

**Returns**

| Name    | Type           | Description                       |
| ------- | -------------- | --------------------------------- |
| `binId` | `uint32`       | The ID of the bin.                |
| `bin`   | `Bin.Instance` | The storage reference to the bin. |

#### \_moveDirection <a href="#movedirection" id="movedirection"></a>

Merges bins and moves them to a new tick.

```solidity
function _moveDirection(MoveData memory moveData) internal;
```

**Parameters**

| Name       | Type       | Description                                                     |
| ---------- | ---------- | --------------------------------------------------------------- |
| `moveData` | `MoveData` | The MoveData struct containing the necessary data for the move. |

#### \_mergeAndDecommissionBin <a href="#mergeanddecommissionbin" id="mergeanddecommissionbin"></a>

Merges a given bin and removes its former tick so that the bin is no longer active.

```solidity
function _mergeAndDecommissionBin(
    uint32 binIdToBeMerged,
    uint32 parentBinId,
    Bin.Instance storage parentBin,
    IMaverickV2Pool.TickState storage parentBinTickState,
    uint8 kind
) internal returns (uint128 binA, uint128 binB, uint128 mergeBinBalance);
```

**Parameters**

| Name                 | Type                        | Description                                                              |
| -------------------- | --------------------------- | ------------------------------------------------------------------------ |
| `binIdToBeMerged`    | `uint32`                    | binId of the bin being merged.                                           |
| `parentBinId`        | `uint32`                    | binId of the parent bin where the merging bin's liquidity is being sent. |
| `parentBin`          | `Bin.Instance`              | Bin object of parent.                                                    |
| `parentBinTickState` | `IMaverickV2Pool.TickState` | Tick object of the parent bin's tick.                                    |
| `kind`               | `uint8`                     | Kind of the bins.                                                        |

#### \_mergeBinsInList <a href="#mergebinsinlist" id="mergebinsinlist"></a>

Merge bins in moveData.mergeBins into firstBin.

```solidity
function _mergeBinsInList(
    Bin.Instance storage firstBin,
    IMaverickV2Pool.TickState storage firstBinTickState,
    MoveData memory moveData
) internal;
```

**Parameters**

| Name                | Type                        | Description                                         |
| ------------------- | --------------------------- | --------------------------------------------------- |
| `firstBin`          | `Bin.Instance`              | The storage reference to the first bin.             |
| `firstBinTickState` | `IMaverickV2Pool.TickState` | The storage reference to the first bin's TickState. |
| `moveData`          | `MoveData`                  | The MoveData struct containing the necessary data.  |

#### \_moveBinToNewTick <a href="#movebintonewtick" id="movebintonewtick"></a>

Move a bin from one tick to another.

```solidity
function _moveBinToNewTick(
    Bin.Instance storage firstBin,
    IMaverickV2Pool.TickState storage startingTickState,
    IMaverickV2Pool.TickState storage endingTickState,
    MoveData memory moveData
) internal;
```

**Parameters**

| Name                | Type                        | Description                                             |
| ------------------- | --------------------------- | ------------------------------------------------------- |
| `firstBin`          | `Bin.Instance`              | The storage reference to the first bin.                 |
| `startingTickState` | `IMaverickV2Pool.TickState` | The storage reference to the starting tick's TickState. |
| `endingTickState`   | `IMaverickV2Pool.TickState` | The storage reference to the ending tick's TickState.   |
| `moveData`          | `MoveData`                  | The MoveData struct containing the necessary data.      |

#### \_getMovementBinsInRange <a href="#getmovementbinsinrange" id="getmovementbinsinrange"></a>

Finds bins of the same kind within the movement search window.

```solidity
function _getMovementBinsInRange(MoveData memory moveData) internal view;
```

#### \_moveBins <a href="#movebins" id="movebins"></a>

Move bins based on TWAP conditions.

Logic looks left and right of the active tick for movement bins. If there is more than one movement bin of the same kind in this multi-tick window, then these bins will get moved to the TWAP tick and merged into to the Bin with the lowest binId.

```solidity
function _moveBins(int32 startingActiveTick, int32 activeTick, int64 lastTwapD8, int64 newTwapD8, int64 boundary)
    internal;
```

**Parameters**

| Name                 | Type    | Description                                                                    |
| -------------------- | ------- | ------------------------------------------------------------------------------ |
| `startingActiveTick` | `int32` | Active tick at the beginning of the swap.                                      |
| `activeTick`         | `int32` | Active tick at the end of the swap.                                            |
| `lastTwapD8`         | `int64` | TWAP at beginning of the swap.                                                 |
| `newTwapD8`          | `int64` | TWAP at end of the swap.                                                       |
| `boundary`           | `int64` | Distance into a tick that a swap has to move in order to cause a bin movement. |

#### \_swapTick <a href="#swaptick" id="swaptick"></a>

Swap tokens at a specific tick.

```solidity
function _swapTick(State memory currentState, Delta.Instance memory delta)
    internal
    returns (Delta.Instance memory newDelta);
```

**Parameters**

| Name           | Type             | Description                                         |
| -------------- | ---------------- | --------------------------------------------------- |
| `currentState` | `State`          | The State struct containing the current state data. |
| `delta`        | `Delta.Instance` | The Delta.Instance struct containing swap data.     |

**Returns**

| Name       | Type             | Description                        |
| ---------- | ---------------- | ---------------------------------- |
| `newDelta` | `Delta.Instance` | The updated Delta.Instance struct. |

#### \_allocateSwapValuesToTick <a href="#allocateswapvaluestotick" id="allocateswapvaluestotick"></a>

Allocate swap values to bins based on token direction and tick.

```solidity
function _allocateSwapValuesToTick(Delta.Instance memory delta, bool tokenAIn, int32 tick) internal;
```

**Parameters**

| Name       | Type             | Description                                               |
| ---------- | ---------------- | --------------------------------------------------------- |
| `delta`    | `Delta.Instance` | The Delta.Instance struct containing swap data.           |
| `tokenAIn` | `bool`           | A boolean indicating whether token A is being swapped in. |
| `tick`     | `int32`          | The int32 value representing the tick.                    |

### Structs <a href="#structs" id="structs"></a>

#### MoveData <a href="#movedata" id="movedata"></a>

Struct for holding data during bin movement.

```solidity
struct MoveData {
    uint8 kind;
    int32 tickSearchStart;
    int32 tickSearchEnd;
    int32 tickLimit;
    int32 firstBinTick;
    uint32 firstBinId;
    uint128 mergeBinBalance;
    uint128 totalReserveA;
    uint128 totalReserveB;
    uint32[MAX_BINS_TO_MERGE] mergeBins;
    uint256 counter;
}
```
