[转] [Uniswap v2 合约代码解析] Uniswap v2 Factory合约代码

概述

Factory合约是Uniswap V2中核心合约代码,所有的Pair合约都是通过Factory合约进行部署。从代码量上以及代码复杂难度上来说,Factory合约的理解难度应该是Uniswap V2合约中比较简单的。

Factory合约代码解析

变量

  • 平台手续费相关

与平台手续费相关有两个变量,均是address,其中address(feeTo)表示平台手续费收取的地址,address(feeToSetter)则表示可设置平台手续费收取地址的地址。

address public feeTo;
address public feeToSetter;
  • Pair合约相关

Pair合约相关有两个变量,其中变量getPair的类型是map,存放Pair合约两个tokenPair合约的地址,格式为address => (address => address)。变量allPairs存放所有Pair合约的地址。

mapping(address => mapping(address => address)) public getPair;
address[] public allPairs;

事件

  • 配对被创建事件

Pair合约被创建之后,会触发该事件。

event PairCreated(address indexed token0, address indexed token1, address pair, uint);

方法

  • 构造函数

Factory合约的构造函数需要传入权限控制人的address

constructor(address _feeToSetter) public {
    feeToSetter = _feeToSetter;
}
  • 查询Pair数组长度方法
function allPairsLength() external view returns (uint) {
    return allPairs.length;
}
  • 创建Pair方法

creatPair方法的功能是创建一组新的交易对,传入的参数是两个token的address,需要注意的是,部署Pair合约使用的是create2方法,使用该方法部署合约可以固定这个合约的地址,使这个合约的地址可预测,这样便于Router合约不进行任何调用,就可以计算得到Pair合约的地址。

function createPair(address tokenA, address tokenB) external returns (address pair) {
    require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES');

    // 对tokenA和tokenB进行大小排序,确保tokenA小于tokenB

    (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
    // 确认token0不等于0地址

    require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS');
    // 确认配对映射中不存在token0=>token1的映射
    require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS'); // single check is sufficient
    // 初始化UniswapV2Pair的字节码变量
    // bytecode 合约经过编译之后的源代码
    bytes memory bytecode = type(UniswapV2Pair).creationCode;
    // 将token0和token1打包后创建哈希
    bytes32 salt = keccak256(abi.encodePacked(token0, token1));
    // 内联汇编
    assembly {
        // 通过create2方法布置合约,并且加salt,返回合约的地址是固定的,可预测的
        pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
    }
    // 调用pair地址的合约的`initialine`方法,传入变量token0和token1

    IUniswapV2Pair(pair).initialize(token0, token1);
    // 配对映射中设置token0=>token1 = pair
    getPair[token0][token1] = pair;
    // 配对映射中设置token1=>token0 = pair
    getPair[token1][token0] = pair; // populate mapping in the reverse direction
    // 配对数组中推入pair地址
    allPairs.push(pair);
    // 触发配对成功事件
    emit PairCreated(token0, token1, pair, allPairs.length);
}
  • 设置平台手续费收取地址

权限控制人合约设定平台手续费是否收取,以及收取的地址。

function setFeeTo(address _feeTo) external {
    require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');
    feeTo = _feeTo;
}
  • 平台手续费收取权限控制

原来的权限控制人,可以指派一个新的address作为新的权限控制人。

function setFeeToSetter(address _feeToSetter) external {
    require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');
    feeToSetter = _feeToSetter;
}

总结

相比核心合约里面的PairERC20合约,Factory合约比较简单。后续会继续解析Uniswap V2中的Router相关合约,Router合约是Uniswap V2运行的关键,前端大部分的操作,都是在与Router合约进行交互。

你可能感兴趣的:(区块链)