了解 SushiSwap 的实现细节
- 原文:https://soliditydeveloper.com/sushi-swap
- 译文出自:登链翻译计划
- 译者:翻译小组
- 校对:Tiny 熊
- 本文永久链接:learnblockchain.cn/article…
你现在可能已经听说过SushiSwap了。其分叉自Uniswap,同时带来了新的功能,比如质押和治理。但它背后的合约究竟是如何运作的呢?
其实这并不难。详细了解这个工作原理将是学习Solidity和Defi的一个好方法。
我们现在将深入SushiSwap的实现细节。为了更容易理解,一些代码被修改了。你可以随时查看Github里面的完整代码。
SushiSwap核心部分只是一个Uniswap v2的分叉。除了一些小的差别,合同代码是完全复制的。如果你对Uniswap v2的工作原理感到好奇,请看我以前的文章这里。在不久的将来对Uniswap v3的深入研究。
特别是SushiSwap正在利用流动性池代币(LP代币)。请查看https://uniswap.org/docs/v2/core-concepts/pools/ 在 LP 代币下的所有细节。从本质上讲,LP是用来接收在流动池中累积的按比例费用。你在一个流动池里提供流动性,并得到LP代币的回报。当资金池现在随着交易的进行收取费用时,它们会在交易时平均分配给所有LP持有人。当你销毁LP代币时,则将收到对应流动池中的资金份额和收集的费用。
SushiSwap对Uniswap代码做了两处修改:
你可以看到Uniswap的核心合约和SushiSwap如何改变它们之间的全部差异这里。
SushiMaker将从SushiSwap上交易的人那里接收LP代币。它主要由一个 convert
函数组成,它的作用如下:
token0
和token1
的数量。convertStep
内将收到的两个代币兑换为SUSHI(代币)。如果没有直接的流动池来兑换为SUSHI,这可能需要额外的步骤。function convert(address token0, address token1) external {
UniV2Pair pair = UniV2Pair(factory.getPair(token0, token1));
require(address(pair) != address(0), "Invalid pair");
IERC20(address(pair)).safeTransfer(
address(pair),
pair.balanceOf(address(this))
);
(uint256 amount0, uint256 amount1) = pair.burn(address(this));
if (token0 != pair.token0()) {
(amount0, amount1) = (amount1, amount0);
}
_convertStep(token0, token1, amount0, amount1)
}
兑换本身也是通过SushiSwap 流动池来进行的。可以通过_swap
函数来看看这是如何做到的。
function _swap(
address fromToken,
address toToken,
uint256 amountIn,
address to
) internal returns (uint256 amountOut) {
UniV2Pair pair =
UniV2Pair(factory.getPair(fromToken, toToken));
require(address(pair) != address(0), "Cannot convert");
(uint256 reserve0, uint256 reserve1, ) = pair.getReserves();
uint256 amountInWithFee = amountIn.mul(997);
if (fromToken == pair.token0()) {
amountOut =
amountInWithFee.mul(reserve1) /
reserve0.mul(1000).add(amountInWithFee);
IERC20(fromToken).safeTransfer(address(pair), amountIn);
pair.swap(0, amountOut, to, new bytes(0));
} else {
amountOut =
amountInWithFee.mul(reserve0) /
reserve1.mul(1000).add(amountInWithFee);
IERC20(fromToken).safeTransfer(address(pair), amountIn);
pair.swap(amountOut, 0, to, new bytes(0));
}
}
开始看到它使用了Uniswap低级别的 swap 函数。
一旦计算出金额,我们就可以进行兑换了。转换为SUSHI的最后一步将总是通过传递SUSHI代币地址来调用_swap
函数,并将其发送到bar:
_swap(token, sushi, amountIn, bar)
就这样,把所有的LP代币转换成了SUSHI,所有转换后的SUSHI都被送到了SushiBar,见下一个合约:
在SushiBar内,人们可以带着SUSHI进入,得到xSUSHI,然后带着更多的SUSHI离开。请记住,所有来自SushiMaker的SUSHI都被送到这里。所以随着时间的推移,SushiBar会积累越来越多的SUSHI。
谁会收到这个SUSHI?
任何进入SushiBar的人。用户进入后会收到xSUSHI,这有点像Uniswap的LP代币。它们代表了SushiBar中SUSHI代币的所有权。
你收到的xSUSHI数量是你转移的SUSHI * xSUSHI发行总量 / SUSHI的当前余额...
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!