图片来源
Uniswap
通过能够孵化
出其它合约的超级合约,建立 ERC20 协议上的合约工厂。
其孵化
出来的合约,定义了用户交易/分红/流动性管理的具体规则。所以,它也扮演了一个去中心化交易所的角色。
本文,基于 Uniswap V2 版本的 UniswapV2Factory 源码,分析 UniswapV2Pair 的创建过程。
UniswapV2-创建 UniswapV2Pair
UniswapV2-添加流动性
UniswapV2-移除流动性
UniswapV2-兑换(swap)
UniswapV2-公式分析
概述
Uniswap
本质上,实际上是一组 ERC20 合约。
它的职责,主要是根据用户操作,将其它 ERC20 Token 对
进行绑定,并将这种绑定结果,定义在其生成的合约内,即创建 Uniswap Pair。这个过程,也可以说是 用合约创建合约。
绑定完成之后,任何人都可以来 SWAP,即通过输入 ERC20 Token 对
中的一种 token 以兑换另外以一种 token;任何人也都可以通过提供注入流动性的方式,成为做市商。
整个过程,都由合约自动完成,这就是去中心化的根本。
基于 Uniswap V2 版本,计划做一个系列,介绍 createPair/swap/addLiquidity/removeLiquidity/分红/无常损失等。本文是第一篇。
创建 UniswapV2Pair
创建过程比较简单,主要是通过 create2
操作符,完成合约的生成。通过源码我们可知:
- 任意两个 token 对(非零) ,都可以生成一个 pair。这两个 token 地址非零即可,UniswapV2Factory 甚至不会去检查这两个 token 是否真的存在。
- 协议费(Protocol Fees)发给谁,由谁来管理发给谁,这些是在 UniswapV2Factory 中控制的。UniswapV2Factory 在构造的时候,确定了 feeSetter; 而是否收取协议费,是通过 feeTo 是否是零地址判断的(这一点后文中 mint 环节将介绍,目前 feeTo 还是零地址,即平台的协议费还没有还是收取)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| contract UniswapV2Factory is IUniswapV2Factory { address public feeTo; address public feeToSetter; mapping(address => mapping(address => address)) public getPair;
address[] public allPairs;
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
constructor(address _feeToSetter) public { feeToSetter = _feeToSetter; }
function allPairsLength() external view returns (uint) { return allPairs.length; }
function createPair(address tokenA, address tokenB) external returns (address pair) { require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES'); (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS'); require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS'); 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; allPairs.push(pair); emit PairCreated(token0, token1, pair, allPairs.length); }
function setFeeTo(address _feeTo) external { require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN'); feeTo = _feeTo; }
function setFeeToSetter(address _feeToSetter) external { require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN'); feeToSetter = _feeToSetter; } }
|
参考链接
Uniswap v2 Core
UniswapV2Factory
Deploying Smart Contracts Using CREATE2