DEV Community

Cover image for [UniswapV2] UniswapV2Pair.sol
MOYED
MOYED

Posted on

[UniswapV2] UniswapV2Pair.sol

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


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. ???


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

    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.

address feeTo = IUniswapV2Factory(factory).feeTo();
feeOn = feeTo != address(0);
Enter fullscreen mode Exit fullscreen mode
  1. For gas saving, we access memory variable instead of storage variable.

    uint _kLast = kLast; // gas savings
    
  2. Liquidity tokens are calculated in following formula which is explained in whitepaper.

    uint numerator = totalSupply.mul(rootK.sub(rootKLast));
    uint denominator = rootK.mul(5).add(rootKLast);
    uint liquidity = numerator / denominator;
    

    Fee Calculationi

  3. _mint from UniswapV2ERC20 is used to create additional liquidity tokens and assign to feeTo address.

    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.

    (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.

    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

    { // 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');
            }
    

Top comments (0)