Compare commits

...

10 Commits

Author SHA1 Message Date
3586e648b2 init
Some checks failed
CI / test (10.x, ubuntu-latest) (push) Has been cancelled
CI / test (12.x, ubuntu-latest) (push) Has been cancelled
2025-07-08 01:27:47 +08:00
ee547b1785 Merge pull request #168 from Uniswap/add-stale
feat: add stale config
2022-07-13 11:47:54 -07:00
b48663b1b5 feat: add stale config 2022-07-13 11:45:04 -07:00
8b82b04a0b Create CITATION.cff (#154)
* Create CITATION.cff

I want to cite this Github repository in some research papers I am writing. A `CITATION.cff` auto generates citations for anyone who may want to reference this repository in their work. See the (docs)[https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-citation-files]. I have drafted this to include the authors of the repository if you desire any changes, please make them.  Thank you.

* Update CITATION.cff

Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>
2022-05-03 10:50:37 -04:00
4dd59067c7 Release v1.0.1. 2020-05-18 18:54:10 -05:00
816b9e3271 Add keywords 2020-05-18 18:53:13 -05:00
8d6bfb3473 Add emoji to description 2020-05-18 18:52:34 -05:00
5419f5409d Generate metadata (#78) 2020-05-18 18:40:32 -05:00
816075049f Release v1.0.0 2020-04-22 12:08:51 -05:00
5e59a166de Couple more clean ups to the package.json 2020-04-22 10:54:27 -05:00
12 changed files with 573 additions and 50 deletions

25
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,25 @@
# Configuration for probot-stale - https://github.com/probot/stale
issues:
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 7
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 7
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels:
- question
- autoclose
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- p0
- bug
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.

View File

@ -9,7 +9,8 @@
"evm.deployedBytecode.object",
"abi",
"evm.bytecode.sourceMap",
"evm.deployedBytecode.sourceMap"
"evm.deployedBytecode.sourceMap",
"metadata"
],
"": ["ast"]
}

15
CITATION.cff Normal file
View File

@ -0,0 +1,15 @@
cff-version: 1.2.0
message: "If you use this software, please cite it as below."
authors:
- family-names: "Zinsmeister"
given-names: "Noah"
- family-names: "Adams"
given-names: "Hayden"
- family-names: "Robinson"
given-names: "Dan"
- family-names: "Salem"
given-names: "Moody"
title: "v2-core"
version: 1.0.1
date-released: 2019-05-03
url: "https://github.com/Uniswap/v2-core"

268
README.md
View File

@ -1,24 +1,270 @@
# Uniswap V2
# Uniswap V2 Core 核心合约
[![Actions Status](https://github.com/Uniswap/uniswap-v2-core/workflows/CI/badge.svg)](https://github.com/Uniswap/uniswap-v2-core/actions)
[![Version](https://img.shields.io/npm/v/@uniswap/v2-core)](https://www.npmjs.com/package/@uniswap/v2-core)
In-depth documentation on Uniswap V2 is available at [uniswap.org](https://uniswap.org/docs).
## 📋 项目概述
The built contract artifacts can be browsed via [unpkg.com](https://unpkg.com/browse/@uniswap/v2-core@latest/).
Uniswap V2 Core 是去中心化交易协议 Uniswap V2 的核心智能合约集合,实现了自动化做市商(AMM)机制。本项目包含了创建和管理流动性池、执行代币交换等核心功能的智能合约。
# Local Development
### 🎯 核心特性
The following assumes the use of `node@>=10`.
- **自动化做市商(AMM)**: 基于恒定乘积公式 `x * y = k` 的去中心化交易
- **流动性挖矿**: 用户可以提供流动性获得手续费收入
- **CREATE2 部署**: 使用确定性地址部署,便于前端集成
- **EIP-712 支持**: 支持链下签名授权,提升用户体验
- **时间加权平均价格(TWAP)**: 内置价格预言机功能
## Install Dependencies
## 🏗️ 项目架构
`yarn`
### 核心合约
## Compile Contracts
```
contracts/
├── UniswapV2Factory.sol # 工厂合约,管理所有交易对的创建
├── UniswapV2Pair.sol # 交易对合约实现AMM核心逻辑
├── UniswapV2ERC20.sol # 流动性代币支持EIP-712
├── interfaces/ # 接口定义
│ ├── IUniswapV2Factory.sol
│ ├── IUniswapV2Pair.sol
│ ├── IUniswapV2ERC20.sol
│ ├── IERC20.sol
│ └── IUniswapV2Callee.sol
├── libraries/ # 工具库
│ ├── Math.sol # 数学运算库
│ ├── SafeMath.sol # 安全数学运算
│ └── UQ112x112.sol # 定点数运算
└── test/ # 测试合约
```
`yarn compile`
### 合约关系图
## Run Tests
```mermaid
graph TB
Factory[UniswapV2Factory<br/>工厂合约] --> Pair[UniswapV2Pair<br/>交易对合约]
Pair --> ERC20[UniswapV2ERC20<br/>流动性代币]
Pair --> SafeMath[SafeMath<br/>安全数学运算]
Pair --> Math[Math<br/>数学库]
Pair --> UQ112x112[UQ112x112<br/>定点数库]
User[用户] --> Factory
User --> Pair
LP[流动性提供者] --> Pair
Trader[交易者] --> Pair
```
`yarn test`
## 🔧 核心概念
### 1. 自动化做市商(AMM)
Uniswap V2 使用恒定乘积公式实现自动化做市:
```
x * y = k
```
其中:
- `x``y` 是池中两种代币的数量
- `k` 是恒定值,只在添加/移除流动性时改变
### 2. 流动性提供
用户可以向交易对提供流动性,获得:
- **流动性代币(LP Token)**: 代表在池中的份额
- **交易手续费**: 每笔交易的0.3%手续费按比例分配
流动性计算公式:
```solidity
// 首次添加流动性
liquidity = sqrt(amount0 * amount1) - MINIMUM_LIQUIDITY
// 后续添加流动性
liquidity = min(amount0 * totalSupply / reserve0, amount1 * totalSupply / reserve1)
```
### 3. 价格发现机制
交易价格由池中代币比例决定:
```
price = reserve1 / reserve0
```
每次交易后,价格会自动调整以维持恒定乘积。
### 4. 时间加权平均价格(TWAP)
合约内置价格累积器,可以计算任意时间段的平均价格:
```solidity
price0CumulativeLast += (reserve1 / reserve0) * timeElapsed
price1CumulativeLast += (reserve0 / reserve1) * timeElapsed
```
## 💼 主要功能
### UniswapV2Factory (工厂合约)
**职责**: 创建和管理所有交易对
**核心函数**:
- `createPair(address tokenA, address tokenB)`: 创建新的交易对
- `getPair(address tokenA, address tokenB)`: 获取交易对地址
- `allPairs(uint index)`: 按索引获取交易对
- `setFeeTo(address feeTo)`: 设置协议费接收地址
**特点**:
- 使用CREATE2确定性部署地址可预测
- 任何人都可以创建交易对
- 自动排序代币地址确保唯一性
### UniswapV2Pair (交易对合约)
**职责**: 实现具体的AMM交易逻辑
**核心函数**:
- `mint(address to)`: 铸造流动性代币
- `burn(address to)`: 销毁流动性代币,取回资产
- `swap(uint amount0Out, uint amount1Out, address to, bytes calldata data)`: 执行代币交换
- `getReserves()`: 获取当前储备量和时间戳
**安全机制**:
- 重入锁防止重入攻击
- 最小流动性锁定防止攻击
- 完整性检查确保K值不减少
### UniswapV2ERC20 (流动性代币)
**职责**: 标准ERC20流动性代币支持高级功能
**核心功能**:
- 标准ERC20功能 (转账、授权等)
- EIP-712签名授权 (`permit`)
- 域分隔符确保跨链安全
## 🚀 快速开始
### 环境要求
- Node.js >= 10
- Yarn 包管理器
### 安装依赖
```bash
yarn install
```
### 编译合约
```bash
yarn compile
```
### 运行测试
```bash
yarn test
```
### 代码检查
```bash
yarn lint
```
## 📖 使用示例
### 1. 部署工厂合约
```solidity
// 部署工厂合约
UniswapV2Factory factory = new UniswapV2Factory(msg.sender);
```
### 2. 创建交易对
```solidity
// 创建 WETH/USDC 交易对
address pair = factory.createPair(WETH, USDC);
```
### 3. 添加流动性
```solidity
// 向交易对转入代币
IERC20(WETH).transfer(pair, wethAmount);
IERC20(USDC).transfer(pair, usdcAmount);
// 铸造流动性代币
uint liquidity = IUniswapV2Pair(pair).mint(msg.sender);
```
### 4. 执行交换
```solidity
// 计算输出数量 (需要使用路由合约)
uint amountOut = getAmountOut(amountIn, reserveIn, reserveOut);
// 转入代币
IERC20(tokenIn).transfer(pair, amountIn);
// 执行交换
IUniswapV2Pair(pair).swap(amount0Out, amount1Out, msg.sender, "");
```
## 🔐 安全考虑
### 重入攻击防护
- 所有状态修改函数都使用重入锁
- 采用检查-生效-交互模式
### 整数溢出防护
- 使用SafeMath库防止算术溢出
- 严格的边界检查
### 经济安全
- 最小流动性锁定(1000 wei)
- K值单调性检查
- 合理的手续费机制
### 前端安全
- CREATE2确定性地址
- 完整的事件日志
- 标准化接口
## 📚 深入学习
### 相关资源
- [Uniswap V2 白皮书](https://uniswap.org/whitepaper.pdf)
- [官方文档](https://uniswap.org/docs)
- [Solidity 最佳实践](https://consensys.github.io/smart-contract-best-practices/)
### 构建工件
编译后的合约可通过 [unpkg.com](https://unpkg.com/browse/@uniswap/v2-core@latest/) 浏览。
## 🤝 贡献指南
欢迎提交 Issue 和 Pull Request
### 开发流程
1. Fork 本仓库
2. 创建功能分支
3. 提交更改
4. 运行测试
5. 提交 Pull Request
## 📄 许可证
本项目采用 [GPL-3.0-or-later](LICENSE) 许可证。
## 🙏 致谢
- Uniswap 团队的创新设计
- DappHub 的 SafeMath 库
- 以太坊社区的支持
---
**⚠️ 风险提示**: 本项目仅供学习和研究使用。在生产环境中使用前,请进行充分的安全审计。去中心化金融存在智能合约风险、无常损失等风险,请谨慎参与。

View File

@ -3,29 +3,42 @@ pragma solidity =0.5.16;
import './interfaces/IUniswapV2ERC20.sol';
import './libraries/SafeMath.sol';
/**
* @title UniswapV2ERC20 流动性代币合约
* @notice 实现ERC20标准的流动性代币支持EIP-712 permit功能
* @dev 为Uniswap V2交易对提供流动性代币功能
*/
contract UniswapV2ERC20 is IUniswapV2ERC20 {
using SafeMath for uint;
string public constant name = 'Uniswap V2';
string public constant symbol = 'UNI-V2';
uint8 public constant decimals = 18;
uint public totalSupply;
mapping(address => uint) public balanceOf;
mapping(address => mapping(address => uint)) public allowance;
// ERC20标准属性
string public constant name = 'Uniswap V2'; // 代币名称
string public constant symbol = 'UNI-V2'; // 代币符号
uint8 public constant decimals = 18; // 小数位数
uint public totalSupply; // 总供应量
mapping(address => uint) public balanceOf; // 余额映射
mapping(address => mapping(address => uint)) public allowance; // 授权映射
bytes32 public DOMAIN_SEPARATOR;
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
// EIP-712相关
bytes32 public DOMAIN_SEPARATOR; // 域分隔符
// permit函数的类型哈希
bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
mapping(address => uint) public nonces;
mapping(address => uint) public nonces; // 防重放nonce
// ERC20标准事件
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
/**
* @dev 构造函数初始化EIP-712域分隔符
*/
constructor() public {
uint chainId;
// 内联汇编获取链ID
assembly {
chainId := chainid
}
// 计算域分隔符
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
@ -37,40 +50,82 @@ contract UniswapV2ERC20 is IUniswapV2ERC20 {
);
}
/**
* @dev 内部函数:铸造代币
* @param to 接收地址
* @param value 铸造数量
*/
function _mint(address to, uint value) internal {
totalSupply = totalSupply.add(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(address(0), to, value);
}
/**
* @dev 内部函数:销毁代币
* @param from 销毁地址
* @param value 销毁数量
*/
function _burn(address from, uint value) internal {
balanceOf[from] = balanceOf[from].sub(value);
totalSupply = totalSupply.sub(value);
emit Transfer(from, address(0), value);
}
/**
* @dev 内部函数:设置授权
* @param owner 授权者
* @param spender 被授权者
* @param value 授权数量
*/
function _approve(address owner, address spender, uint value) private {
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
/**
* @dev 内部函数:转账
* @param from 发送者
* @param to 接收者
* @param value 转账数量
*/
function _transfer(address from, address to, uint value) private {
balanceOf[from] = balanceOf[from].sub(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(from, to, value);
}
/**
* @notice 授权spender使用value数量的代币
* @param spender 被授权地址
* @param value 授权数量
* @return 是否成功
*/
function approve(address spender, uint value) external returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
/**
* @notice 转账代币给to地址
* @param to 接收地址
* @param value 转账数量
* @return 是否成功
*/
function transfer(address to, uint value) external returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
/**
* @notice 从from地址转账代币给to地址需要授权
* @param from 发送地址
* @param to 接收地址
* @param value 转账数量
* @return 是否成功
*/
function transferFrom(address from, address to, uint value) external returns (bool) {
// 如果授权量不是最大值,则减少授权量
if (allowance[from][msg.sender] != uint(-1)) {
allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
}
@ -78,17 +133,33 @@ contract UniswapV2ERC20 is IUniswapV2ERC20 {
return true;
}
/**
* @notice EIP-712签名授权无需发送交易即可设置授权
* @param owner 代币所有者
* @param spender 被授权者
* @param value 授权数量
* @param deadline 授权截止时间
* @param v 签名参数v
* @param r 签名参数r
* @param s 签名参数s
*/
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
require(deadline >= block.timestamp, 'UniswapV2: EXPIRED');
// 构造EIP-712消息哈希
bytes32 digest = keccak256(
abi.encodePacked(
'\x19\x01',
'\x19\x01', // EIP-191前缀
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
)
);
// 恢复签名者地址
address recoveredAddress = ecrecover(digest, v, r, s);
require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE');
// 设置授权
_approve(owner, spender, value);
}
}

View File

@ -3,45 +3,94 @@ 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'); // single check is sufficient
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; // populate mapping in the reverse direction
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;

View File

@ -8,26 +8,42 @@ import './interfaces/IERC20.sol';
import './interfaces/IUniswapV2Factory.sol';
import './interfaces/IUniswapV2Callee.sol';
/**
* @title UniswapV2Pair 交易对合约
* @notice 这是Uniswap V2协议的核心合约实现了自动做市商(AMM)机制
* @dev 继承自IUniswapV2Pair接口和UniswapV2ERC20合约实现流动性代币功能
*/
contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
using SafeMath for uint;
using UQ112x112 for uint224;
// 最小流动性常量,防止除零错误和攻击
uint public constant MINIMUM_LIQUIDITY = 10**3;
// ERC20 transfer函数的选择器用于安全转账
bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));
// 工厂合约地址
address public factory;
// 交易对中的两个代币地址token0 < token1
address public token0;
address public token1;
uint112 private reserve0; // uses single storage slot, accessible via getReserves
uint112 private reserve1; // uses single storage slot, accessible via getReserves
uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves
// 储备量使用uint112节省gas三个变量共用一个存储槽
uint112 private reserve0; // token0的储备量
uint112 private reserve1; // token1的储备量
uint32 private blockTimestampLast; // 上次更新的区块时间戳
uint public price0CumulativeLast;
uint public price1CumulativeLast;
uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event
// 价格累积器,用于计算时间加权平均价格(TWAP)
uint public price0CumulativeLast; // token0相对于token1的累积价格
uint public price1CumulativeLast; // token1相对于token0的累积价格
uint public kLast; // 上次流动性事件后的k值 (reserve0 * reserve1)
// 重入锁状态
uint private unlocked = 1;
/**
* @dev 重入锁修饰符,防止重入攻击
*/
modifier lock() {
require(unlocked == 1, 'UniswapV2: LOCKED');
unlocked = 0;
@ -35,17 +51,30 @@ contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
unlocked = 1;
}
/**
* @notice 获取当前储备量和最后更新时间
* @return _reserve0 token0的储备量
* @return _reserve1 token1的储备量
* @return _blockTimestampLast 最后更新的区块时间戳
*/
function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
_reserve0 = reserve0;
_reserve1 = reserve1;
_blockTimestampLast = blockTimestampLast;
}
/**
* @dev 安全转账函数,确保代币转账成功
* @param token 代币合约地址
* @param to 接收地址
* @param value 转账数量
*/
function _safeTransfer(address token, address to, uint value) private {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED');
}
// 事件定义
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
@ -58,13 +87,20 @@ contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
);
event Sync(uint112 reserve0, uint112 reserve1);
/**
* @dev 构造函数,设置工厂地址为部署者
*/
constructor() public {
factory = msg.sender;
}
// called once by the factory at time of deployment
/**
* @notice 初始化交易对,只能由工厂调用一次
* @param _token0 第一个代币地址
* @param _token1 第二个代币地址
*/
function initialize(address _token0, address _token1) external {
require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check
require(msg.sender == factory, 'UniswapV2: FORBIDDEN');
token0 = _token0;
token1 = _token1;
}

View File

@ -1,17 +1,34 @@
pragma solidity >=0.5.0;
/**
* @title IUniswapV2Factory 工厂合约接口
* @notice 定义Uniswap V2工厂合约的标准接口
*/
interface IUniswapV2Factory {
/// @notice 创建新交易对时触发的事件
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
/// @notice 协议手续费接收地址
function feeTo() external view returns (address);
/// @notice 有权设置feeTo的地址
function feeToSetter() external view returns (address);
/// @notice 获取指定代币对的交易对地址
function getPair(address tokenA, address tokenB) external view returns (address pair);
/// @notice 按索引获取交易对地址
function allPairs(uint) external view returns (address pair);
/// @notice 获取交易对总数
function allPairsLength() external view returns (uint);
/// @notice 创建新的交易对
function createPair(address tokenA, address tokenB) external returns (address pair);
/// @notice 设置协议手续费接收地址
function setFeeTo(address) external;
/// @notice 设置手续费设置者地址
function setFeeToSetter(address) external;
}

View File

@ -1,17 +1,32 @@
pragma solidity =0.5.16;
// a library for performing various math operations
/**
* @title Math 数学计算库
* @notice 提供各种数学运算函数
* @dev 包含最小值计算和平方根计算等工具函数
*/
library Math {
/**
* @notice 返回两个数中的较小值
* @param x 第一个数
* @param y 第二个数
* @return z 较小的数
*/
function min(uint x, uint y) internal pure returns (uint z) {
z = x < y ? x : y;
}
// babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
/**
* @notice 计算平方根(巴比伦算法)
* @dev 使用巴比伦方法计算平方根,参考: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
* @param y 需要计算平方根的数
* @return z 平方根结果
*/
function sqrt(uint y) internal pure returns (uint z) {
if (y > 3) {
z = y;
uint x = y / 2 + 1;
// 迭代逼近,直到找到最优解
while (x < z) {
z = x;
x = (y / x + x) / 2;
@ -19,5 +34,6 @@ library Math {
} else if (y != 0) {
z = 1;
}
// 如果y为0则z保持为0默认值
}
}

View File

@ -1,16 +1,41 @@
pragma solidity =0.5.16;
// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
/**
* @title SafeMath 安全数学运算库
* @notice 提供防止溢出的数学运算函数
* @dev 来自DappHub的ds-math库 (https://github.com/dapphub/ds-math)
* @dev 在Solidity 0.8.0之前,需要手动检查算术溢出
*/
library SafeMath {
/**
* @notice 安全加法,防止溢出
* @param x 第一个加数
* @param y 第二个加数
* @return z 两数之和
* @dev 如果结果溢出则回滚交易
*/
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, 'ds-math-add-overflow');
}
/**
* @notice 安全减法,防止下溢
* @param x 被减数
* @param y 减数
* @return z 两数之差
* @dev 如果结果下溢则回滚交易
*/
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, 'ds-math-sub-underflow');
}
/**
* @notice 安全乘法,防止溢出
* @param x 第一个乘数
* @param y 第二个乘数
* @return z 两数之积
* @dev 如果结果溢出则回滚交易,使用除法检查溢出
*/
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
}

View File

@ -1,19 +1,32 @@
pragma solidity =0.5.16;
// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
// range: [0, 2**112 - 1]
// resolution: 1 / 2**112
/**
* @title UQ112x112 定点数运算库
* @notice 处理二进制定点数的库 (Q数字格式)
* @dev 参考: https://en.wikipedia.org/wiki/Q_(number_format)
* @dev 范围: [0, 2**112 - 1],精度: 1 / 2**112
*/
library UQ112x112 {
// Q112常量表示2^112用于编码和解码
uint224 constant Q112 = 2**112;
// encode a uint112 as a UQ112x112
/**
* @notice 将uint112编码为UQ112x112格式
* @param y 要编码的uint112数值
* @return z 编码后的UQ112x112数值
* @dev 乘以Q112进行编码永不溢出
*/
function encode(uint112 y) internal pure returns (uint224 z) {
z = uint224(y) * Q112; // never overflows
z = uint224(y) * Q112; // 永不溢出
}
// divide a UQ112x112 by a uint112, returning a UQ112x112
/**
* @notice UQ112x112除以uint112返回UQ112x112
* @param x UQ112x112格式的被除数
* @param y uint112格式的除数
* @return z UQ112x112格式的商
* @dev 用于价格计算,保持定点数精度
*/
function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
z = x / uint224(y);
}

View File

@ -1,14 +1,23 @@
{
"name": "@uniswap/v2-core",
"version": "1.0.0-beta.3",
"files": [
"contracts",
"build"
],
"description": "🎛 Core contracts for the UniswapV2 protocol",
"version": "1.0.1",
"homepage": "https://uniswap.org",
"repository": {
"type": "git",
"url": "https://github.com/Uniswap/uniswap-v2-core"
},
"keywords": [
"uniswap",
"ethereum",
"v2",
"core",
"uniswap-v2"
],
"files": [
"contracts",
"build"
],
"engines": {
"node": ">=10"
},