[UniswapV2] UniswapV2Pair.sol
Tags: uniswap, ethereum, solidity, web3
Published: 2022-01-05 14:11:49

## Variables

### MINIMUM_LIQUIDITY

`MINIMUM_LIQUIDITY` is the minimum amount of liquidity burned at first liquidity provision. 

### SELECTOR

ABI selector for `transfer` function. 

### kLast

`kLast` is value of `reserve0` * `reserve1` . Uniswap keeps `kLast` constant, and decides the exchange rate based on it. 

![Example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l01b3zkabvjktqmivjrd.png)
 

---

## Modifiers

### Lock

`Lock` modifier prevent functions from being called while they are running.(within the same transaction).

Function is called only when `unlocked` is 1. While the function is running the value of `unlocked` is 0. 

---

## Misc. Functions

### getReserves (public)

Returns current `reserve0`, `reserve1` , `blockTimestampLast` .

### _safeTransfer (private)

Transfer `value` of ERC20 tokens from the exchange to `to` . `SELECTOR` specifies that function we are calling is `transfer(address,uint)` . 

> To avoid having to import an interface for the token function, we "manually" create the call using one of the [ABI functions](https://docs.soliditylang.org/en/v0.8.3/units-and-global-variables.html#abi-encoding-and-decoding-functions). ???
> 

---

## Events

### Mint

When liquidity provider deposit liquidity.

### Burn

When liquidity provider withdraw liquidity.

### Swap

When trader swap tokens.

### Sync

Provide latest reserve information, every tokens are added or withdrawn. 

---

## Setup Functions

### constructor

Set `factory` to the deployer of this contract.

### initialize

Initialize the address of the two ERC-20 tokens that consist the pair. Only possible for `factory` address.

---

## Internal Update Functions

### _update (private)

Called every time tokens are deposited or withdrawn. 

1. Measure `timeElapsed` which is time passed from last block timestamp and current one.
2. Update the cumulative price of token1 and token2. 
    
    > Cumulative price of token 0 += reserve1/reserve0 * timeElapsed
    > 
    
    ```solidity
    price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
    price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
    ```
    
3. Update new reserves and block timestamp. 

### _mintFee

0.05% of protocol fee may go to Uniswap if the factory choose to do it.

If `factory` assigned `feeTo` variable, 0.05% of fee goes to Uniswap.

```solidity
address feeTo = IUniswapV2Factory(factory).feeTo();
feeOn = feeTo != address(0);
```

1. For gas saving, we access memory variable instead of storage variable. 

    ```solidity
    uint _kLast = kLast; // gas savings
    ```

2. Liquidity tokens are calculated in following formula which is explained in whitepaper.
    
    ```solidity
    uint numerator = totalSupply.mul(rootK.sub(rootKLast));
    uint denominator = rootK.mul(5).add(rootKLast);
    uint liquidity = numerator / denominator;
    ```
    ![Fee Calculationi](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x44zegznc42ubal6uq9s.png)
    


 

3. `_mint` from UniswapV2ERC20 is used to create additional liquidity tokens and assign to `feeTo` address.
    
    ```solidity
    if (liquidity > 0) _mint(feeTo, liquidity);
    ```
    

---

## External accessible functions

Still, it’s not recommended to call this functions; used periphery contract.

### mint

Called when liquidity provide adds liquidity to the pool. It mints additional liquidity tokens as a reward. 

1. We calculate how much is added by subtracting the reserves from balance of this address.
    
    ```solidity
    (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
    uint balance0 = IERC20(token0).balanceOf(address(this));
    uint balance1 = IERC20(token1).balanceOf(address(this));
    uint amount0 = balance0.sub(_reserve0);
    uint amount1 = balance1.sub(_reserve1);
    ```
    
2. Calculate the protocol fee, if it exists. The parameter is based on old reserve values. 
    
    ```solidity
    bool feeOn = _mintFee(_reserve0, _reserve1); 
    ```
    
3. If it is the first deposit, create `MINIMUM_LIQUIDITY` tokens and send them to address zero to lock them. Initial liquidity is measured to square of `reserve0` * `reserve1` . 
4. Liquidity token is minted based on the amount the liquidity provider provided relative to reserve. `_mint`  is used.

### burn

Called when liquidity is withdrawn and regarding liquidity tokens need to be burned. Should be called from periphery account. 

### swap

Swap token

- What I don’t get it
    
    ```solidity
    { // scope for reserve{0,1}Adjusted, avoids stack too deep errors
      uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));
      uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));
      require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K');
            }
    ```