Solidity Uniswap V2 Router contract addLiquidity

router 合约是一种高级合约,是大多数用户应用程序的入口点。通过该合约,可以更轻松地创建交易对、添加和删除流动性、计算交换中的价格变化以及执行交换。Router 适用于通过工厂合约部署的所有交易对,是一种通用合约。

GitHub - XuHugo/solidityproject: DApp go go go !!!

它也是一个非常大的合约,我们可能不会实现它的所有功能,因为其中大部分都是交换功能的变形。让我们看看路由器的构造函数:路由器可以部署pair,因此它需要知道工厂合约的地址。

复制代码
contract ZuniswapV2Router {

    error InsufficientAAmount();

    error InsufficientBAmount();

    error SafeTransferFailed();



    IZuniswapV2Factory factory;



    constructor(address factoryAddress) {

        factory = IZuniswapV2Factory(factoryAddress);

    }

    ...

今天,我们只实现流动性管理的一部分,让我们从 addLiquidity 开始:

复制代码
function addLiquidity(

    address tokenA,

    address tokenB,

    uint256 amountADesired,

    uint256 amountBDesired,

    uint256 amountAMin,

    uint256 amountBMin,

    address to

)

    public

    returns (

        uint256 amountA,

        uint256 amountB,

        uint256 liquidity

    )

    ...

与pair合约中的mint函数相比,该函数有很多参数!

1、tokenA 和 tokenB 用于查找(或创建)我们希望增加流动性的货币对。

2、amountADesired 和 amountBDesired 是我们希望存入货币对的金额。这些是上限。

3、amountAMin 和 amountBMin 是我们希望存入的最小金额。还记得当我们存入不平衡的流动性时,pair合约总是发行较少的 LP-Token吗?。因此,最小参数允许我们控制准备损失多少流动性。

4、to 地址是接收 LP-Token的地址。

复制代码
...

if (factory.pairs(tokenA, tokenB) == address(0)) {

    factory.createPair(tokenA, tokenB);

}

...

如果指定的ERC20 Token没有pair合约,它将由router 合约创建。 factory.pairs方法是pairs映射,由于映射是嵌套的,Solidity 为该辅助方法设置了两个参数。

复制代码
...

(amountA, amountB) = _calculateLiquidity(

    tokenA,

    tokenB,

    amountADesired,

    amountBDesired,

    amountAMin,

    amountBMin

);

...

下一步,我们将计算将存入的金额。稍后我们将回到这个函数。

复制代码
...

address pairAddress = ZuniswapV2Library.pairFor(

    address(factory),

    tokenA,

    tokenB

);

_safeTransferFrom(tokenA, msg.sender, pairAddress, amountA);

_safeTransferFrom(tokenB, msg.sender, pairAddress, amountB);

liquidity = IZuniswapV2Pair(pairAddress).mint(to);

...

计算完流动性金额后,我们就可以从用户处转移token,并铸造 LP-token作为交换。除了 pairFor 函数之外,这些代码中的大部分你都应该很熟悉了,我们将在实现 _calculateLiquidity 之后立即实现它。此外,请注意该合约并不希望用户手动转移代币,而是使用 ERC20 transferFrom 函数从用户余额中转移代币。

复制代码
function _calculateLiquidity(

    address tokenA,

    address tokenB,

    uint256 amountADesired,

    uint256 amountBDesired,

    uint256 amountAMin,

    uint256 amountBMin

) internal returns (uint256 amountA, uint256 amountB) {

    (uint256 reserveA, uint256 reserveB) = ZuniswapV2Library.getReserves(

        address(factory),

        tokenA,

        tokenB

    );



    ...

在这个函数中,我们要找到满足我们所需和最低金额的流动性金额。由于从我们在用户界面选择流动性金额到我们的交易被处理之间存在延迟,实际reserve比率可能会发生变化,这将导致我们损失一些 LP-token(作为对存入不平衡流动性的惩罚)。通过选择所需的最小金额,我们可以最大限度地减少这种损失。

该功能的第一步是通过使用库合约获取池储备,我们下次就会实现这一点。得到了reserve,我们就可以计算出最佳流动性金额

复制代码
...

if (reserveA == 0 && reserveB == 0) {

    (amountA, amountB) = (amountADesired, amountBDesired);

...

如果储备金是空的,那么这是一对新的货币对,这意味着我们的流动性将决定储备金比率,这意味着我们不会因为提供不平衡的流动性而受到惩罚。因此,我们可以存入所需的全额资金。

复制代码
...

} else {

    uint256 amountBOptimal = ZuniswapV2Library.quote(

        amountADesired,

        reserveA,

        reserveB

    );

    if (amountBOptimal <= amountBDesired) {

        if (amountBOptimal <= amountBMin) revert InsufficientBAmount();

        (amountA, amountB) = (amountADesired, amountBOptimal);

...

否则,我们需要找到最优数量,我们从找到最优tokenB数量开始。报价是库合约中的另一个函数:通过输入金额和配对储备金,计算输出金额,即tokenA 的价格乘以token B 的输入金额。

如果amountBOptimal 小于或等于我们的期望金额,并且高于我们的最小金额,则使用该金额。期望金额和最小金额之间的差额可以防止滑点。

但是,如果最优金额BOptimal 大于我们的期望金额,则不能使用,我们需要找到另一个最优金额 A。

复制代码
...

} else {

    uint256 amountAOptimal = ZuniswapV2Library.quote(

        amountBDesired,

        reserveB,

        reserveA

    );

    assert(amountAOptimal <= amountADesired);



    if (amountAOptimal <= amountAMin) revert InsufficientAAmount();

    (amountA, amountB) = (amountAOptimal, amountBDesired);

}

使用相同的逻辑,我们可以找到 amountAOptimal:它也必须在我们的最小期望范围内。

相关推荐
数据与人工智能律师2 小时前
数字资产革命中的信任之锚:RWA法律架构的隐形密码
大数据·网络·人工智能·云计算·区块链
小赖同学啊5 小时前
区块链技术在物联网(IoT)中的核心应用场景
物联网·区块链
YSGZJJ10 小时前
股指期货空头减仓说明了什么?
区块链
小赖同学啊10 小时前
基于区块链的物联网(IoT)安全通信与数据共享的典型实例
物联网·安全·区块链
TechubNews15 小时前
东方之珠·数链未来:香港回归28周年RWA革命赋能全球金融
区块链·稳定币
yoona10201 天前
在 Sepolia 上使用 Zama fhEVM 构建隐私代币与流动性池:全流程实战指南
区块链·隐私币·zama
选择不变1 天前
日线周线MACD指标使用图文教程,通达信指标
大数据·区块链·通达信指标公式·炒股技巧·短线指标·炒股指标
nicepainkiller1 天前
anchor 智能合约案例3 之 journal
人工智能·智能合约·solana·anchor
nicepainkiller1 天前
anchor 智能合约案例2 之 vote
人工智能·智能合约·solana·anchor
链上Sniper1 天前
智能合约状态快照技术:实现 EVM 状态的快速同步与回滚
java·大数据·linux·运维·web3·区块链·智能合约