Uniswap 工厂合约创建配对合约
uniswap 里有一个工厂合约,作用是创建交易对合约,每添加一个交易对都会创建一个配对合约。uniswapv2 里使用的是内联汇编创建合约,这种方式比较复杂,先获取配对合约的字节码,再获取 token0 和 token1 打包后的哈希,然后调用 create2 创建合约,主要代码如下:
1 2 3 4 5 6 |
bytes memory bytecode = type(UniswapV2Pair).creationCode; bytes32 salt = keccak256(abi.encodePacked(token0, token1)); assembly { pair := create2(0, add(bytecode, 32), mload(bytecode), salt) } |
我们可以使用一种简单的方式创建合约,使用 new 语句创建合约,实现一个简版的 uniswap 工厂合约创建配对合约。
ERC20 代币
uniswap 里的交易对是两个 ERC20 代币,我们需要完成两个 ERC20 代币合约,比如一个是 WETH,一个是 USDC。什么才算是 ERC20 标准?只要满足 ERC20 对应的几个接口就可以称为满足 ERC20 标准,至于每个接口里的逻辑怎么实现没有要求,每个接口的功能,在代码里做了注释,不再细化讲解。
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 60 61 62 |
pragma solidity ^0.8.0; interface IERC20 { function totalSupply() external view returns (uint); //总量 function balanceOf(address account) external view returns (uint); //查询用户币数 function transfer(address recipient, uint amount) external returns (bool); //转账 function allowance(address owner, address spender) external view returns (uint); //查询授权多少币 function approve(address spender, uint amount) external returns (bool); //授权多少币给 spender function transferFrom(address sender, address recipient, uint amount) external returns (bool); //从 sender 转账给 recipient event Transfer(address indexed from, address indexed to, uint amount); //转账事件 event Approval(address indexed owner, address indexed spender, uint amount); //授权事件 } contract WETH is IERC20 { string public name = "Wrapped Ether"; string public symbol = "WETH"; uint private decimals = 18; uint private _totalSupply = 100; mapping(address => uint) private _balances; mapping(address => mapping(address => uint)) private _allowances; constructor(){ _balances[msg.sender] = _totalSupply; } function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } function transfer(address recipient, uint amount) public virtual override returns (bool){ _balances[msg.sender] -= amount; _balances[recipient] += amount; emit Transfer(msg.sender, recipient, amount); return true; } function approve(address spender, uint amount) public virtual override returns (bool){ _allowances[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transferFrom(address sender, address recipient, uint amount) public virtual override returns (bool){ _allowances[sender][msg.sender] -= amount; _balances[sender] -= amount; _balances[recipient] += amount; emit Transfer(sender, recipient, amount); return true; } function totalSupply() public view virtual override returns (uint){ return _totalSupply; } function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } } |
选择 WETH.sol 文件,按快捷键 control + s (macOS 是 command + s) 可以编译文件,然后点 Depoly 布署,布署完后的效果如下图。如果布署 USDC 代币只需要将 name 和 symbol 修改,其他代码和 WETH 保持一样。
配对合约
配对合约名称为 Pair,有三个变量,factory 记录了工厂合约地址,它也可以做为最初的 owner,tokenA 是交易对的第一个币,tokenB 是交易对的第二个币。Pair 合约还有一个构造函数,添加了 payable,说明可以接受主币 ETH,具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
contract Pair { address public factory; address public tokenA; address public tokenB; constructor(address _tokenA, address _tokenB) public payable{ factory = msg.sender; tokenA = _tokenA; tokenB = _tokenB; } } |
工厂合约
工厂合约名称为 Factory,由于工厂合约可以创建 N 个配对合约,所以需要一个数组,用于记录了所有配对合约地址。定义了一个 createPair 函数用来创建合约,有两个参数,即 tokenA 和 token B 的地址,使用 new 语句创建配对合约,并且转 1 wei 主币给创建后的合约,传入 tokenA 和 tokenB 的地址到配对合约的构造函数。最后将创建后的合约地址记录到 allPairs 数组。
1 2 3 4 5 6 7 8 9 |
contract Factory { Pair[] public allPairs; //数组,记录了所有配对合约地址 function createPair(address tokenA, address tokenB) external payable{ Pair pair = new Pair{value: 1}(tokenA, tokenB); //转 1wei 主币ETH,传入tokenA和tokenB到配对合约的构造函数。 allPairs.push(pair); //记录创建后的合约地址 } } |
布署完工厂合约,在 createPair 接口参数填入 WETH 和 USDC 的合约地址,并给 1wei 主币,执行创建操作,如下图所示:
配对合约创建成功后,在工厂合约的 allPairs 数组里可以获取到合约地址,有了合约地址,选择 Pair 合约名称,填入合约地址,点击 At Address 就能加载配对合约,如下图所示:
配对合约加载完成后,可以看到有三个变量,factory 对应了工厂合约地址,tokenA 对应了 WETH,tokenB 对应了 USDC,如下图所示,至此我们完成了一个简单的工厂合约创建配对合约的功能。
转载请注明:exchen's blog » Uniswap 工厂合约创建配对合约