99 lines
3.3 KiB
Solidity
99 lines
3.3 KiB
Solidity
pragma solidity =0.5.16;
|
||
|
||
import './interfaces/IUniswapV2Factory.sol';
|
||
import './UniswapV2Pair.sol';
|
||
|
||
/**
|
||
* @title UniswapV2Factory 工厂合约
|
||
* @notice Uniswap V2协议的工厂合约,负责创建和管理所有交易对
|
||
* @dev 使用CREATE2确定性部署,可预测交易对地址
|
||
*/
|
||
contract UniswapV2Factory is IUniswapV2Factory {
|
||
// 协议手续费接收地址
|
||
address public feeTo;
|
||
// 有权设置feeTo的地址
|
||
address public feeToSetter;
|
||
|
||
// 双重映射:token地址 => token地址 => 交易对地址
|
||
mapping(address => mapping(address => address)) public getPair;
|
||
// 所有交易对地址的数组
|
||
address[] public allPairs;
|
||
|
||
// 创建交易对时触发的事件
|
||
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
|
||
|
||
/**
|
||
* @dev 构造函数
|
||
* @param _feeToSetter 初始的手续费设置者地址
|
||
*/
|
||
constructor(address _feeToSetter) public {
|
||
feeToSetter = _feeToSetter;
|
||
}
|
||
|
||
/**
|
||
* @notice 获取所有交易对的数量
|
||
* @return 交易对总数
|
||
*/
|
||
function allPairsLength() external view returns (uint) {
|
||
return allPairs.length;
|
||
}
|
||
|
||
/**
|
||
* @notice 创建交易对
|
||
* @dev 使用CREATE2确定性部署,任何人都可以调用
|
||
* @param tokenA 第一个代币地址
|
||
* @param tokenB 第二个代币地址
|
||
* @return pair 新创建的交易对地址
|
||
*/
|
||
function createPair(address tokenA, address tokenB) external returns (address pair) {
|
||
require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES');
|
||
// 按字典顺序排序代币地址,确保token0 < token1
|
||
(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');
|
||
|
||
// 获取UniswapV2Pair合约的字节码
|
||
bytes memory bytecode = type(UniswapV2Pair).creationCode;
|
||
// 使用两个代币地址生成salt
|
||
bytes32 salt = keccak256(abi.encodePacked(token0, token1));
|
||
|
||
// 使用CREATE2部署合约,地址可预测
|
||
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);
|
||
}
|
||
|
||
/**
|
||
* @notice 设置协议手续费接收地址
|
||
* @dev 只有feeToSetter可以调用
|
||
* @param _feeTo 新的手续费接收地址
|
||
*/
|
||
function setFeeTo(address _feeTo) external {
|
||
require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');
|
||
feeTo = _feeTo;
|
||
}
|
||
|
||
/**
|
||
* @notice 设置有权修改feeTo的地址
|
||
* @dev 只有当前feeToSetter可以调用
|
||
* @param _feeToSetter 新的手续费设置者地址
|
||
*/
|
||
function setFeeToSetter(address _feeToSetter) external {
|
||
require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');
|
||
feeToSetter = _feeToSetter;
|
||
}
|
||
}
|