I'm looking at the function swap that allows a user to swap token0 for token1 from Uniswaps UniswapV2Pair contract - https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2Pair.sol.

One thing that is unclear to me is how a user can specify which tokens they want to swap. It seems that _token1 and _token2 are both state variables that can't be set by the user. My suspicion is that it can be set in the "data" argument but I'm unsure how passing the relevant info in the data argument sets the state variables.

    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {

        require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT');
        (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
        require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY');

        uint balance0;
        uint balance1;

        { // scope for _token{0,1}, avoids stack too deep errors
        address _token0 = token0;
        address _token1 = token1;
        require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO');
        if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
        if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
        if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data);
        balance0 = IERC20(_token0).balanceOf(address(this));
        balance1 = IERC20(_token1).balanceOf(address(this));
        uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
        uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
        require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT');

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


        _update(balance0, balance1, _reserve0, _reserve1);
        emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);


The values for token0 and token1 are provided by the factory contract at the time of contract deployment.

AFAIK, there is a separate contract for Each Pair of tokens deployed by using the Factory pattern and hence they don't need to configured/supplied by users.

enter image description here


To further clarify, the user doesnt interact at all with UniswapV2Pair. When buying or selling tokens they interact with UniswapV2Router, where they can specify a path, and then the router redirects the transaction to the correct UniswapV2Pair contract

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.