Untitled

 avatar
unknown
plain_text
3 years ago
5.6 kB
2
Indexable
contract UniswapV2Router02 is IUniswapV2Router02 {
    using SafeMath for uint;

    // insert uniswap factory address !
    address public immutable override factory;

    // insert WETH contract address
    address public immutable override WETH;

    //modifire for check deadline
    modifier ensure(uint deadline) {
        require(deadline >= block.timestamp, 'UniswapV2Router: EXPIRED');
        _;
    }

    // set our arguments
    constructor(address _factory, address _WETH) public {
        factory = _factory;
        WETH = _WETH;
    }

    receive() external payable {
        assert(msg.sender == WETH); // only accept ETH via fallback from the WETH contract
    }

    // **** ADD LIQUIDITY ****
    function _addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin
    ) internal virtual returns (uint amountA, uint amountB) {
        // create the pair if it doesn't exist yet
        if (IUniswapV2Factory(factory).getPair(tokenA, tokenB) == address(0)) {
            //we create pair for token A and token B with V2 factory and create pair function!
            IUniswapV2Factory(factory).createPair(tokenA, tokenB);

        /*

    function createPair(address tokenA, address tokenB) external returns (address pair) {

        //check address token a != address tokenB
        require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES');

        // set Token0 and Token1 to TokenA or TokenB !
        (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);

        // check token0 address
        require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS');

        //check pair token0 and tokenb is not exist !
        require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS'); // single check is sufficient


        bytes memory bytecode = type(UniswapV2Pair).creationCode;
        bytes32 salt = keccak256(abi.encodePacked(token0, token1));
        assembly {
            pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
        }


        IUniswapV2Pair(pair).initialize(token0, token1);
        getPair[token0][token1] = pair;
        getPair[token1][token0] = pair; // populate mapping in the reverse direction

        allpairs array push new pair!
        allPairs.push(pair);
        emit PairCreated(token0, token1, pair, allPairs.length);
    }

        */
        }

        // else ger reserve of tokena and tokenb from UniswapV2Library and getReserves function
        (uint reserveA, uint reserveB) = UniswapV2Library.getReserves(factory, tokenA, tokenB);

        /* 
        
        function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) {

        //use sortTokens function to get address token0
        (address token0,) = sortTokens(tokenA, tokenB);
        (uint reserve0, uint reserve1,) = IUniswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves();
        (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
    }
        
        */
        if (reserveA == 0 && reserveB == 0) {

            //if reserves from UniswapV2Library.getReserves(factory, tokenA, tokenB) are 0 ! so we set amounta and amountb to amountADesired and amountBDesired
            (amountA, amountB) = (amountADesired, amountBDesired);
        } else {          

            /* 

        we calculate amountBOptimal with UniswapV2Library.quote function. in this function we got RA and RB from UniswapV2Library.getReserves and we have amountADesired

            
        function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) {
        require(amountA > 0, 'UniswapV2Library: INSUFFICIENT_AMOUNT');
        require(reserveA > 0 && reserveB > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
        amountB = amountA.mul(reserveB) / reserveA;
    }
            
             */
            uint amountBOptimal = UniswapV2Library.quote(amountADesired, reserveA, reserveB);

            //
            if (amountBOptimal <= amountBDesired) {
                // we need amount B to be more than amountBMin if amountBOptimal <= amountBDesired
                require(amountBOptimal >= amountBMin, 'UniswapV2Router: INSUFFICIENT_B_AMOUNT');
                (amountA, amountB) = (amountADesired, amountBOptimal);
            } else {
                uint amountAOptimal = UniswapV2Library.quote(amountBDesired, reserveB, reserveA);
                assert(amountAOptimal <= amountADesired);
                require(amountAOptimal >= amountAMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT');
                (amountA, amountB) = (amountAOptimal, amountBDesired);
            }
        }
    }


    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external virtual override ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) {
        (amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin);
        address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB);
        TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA);
        TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB);
        liquidity = IUniswapV2Pair(pair).mint(to);
    }