这篇文章主要介绍了详解 SushiSwap ,文中通过代码以及文档配合进行讲解,很详细,它对在座的每个人的研究和工作具有很经典的参考价值。 如果需要,让我们与区块链资料网一起学习。

https://www.interchains.cc/23054.html

详解 SushiSwap是很好的区块链资料,他说明了区块链当中的经典原理,可以给我们提供资料,详解 SushiSwap学习起来其实是很简单的,

不多的几个较为抽象的概念也很容易理解,之所以很多人感觉详解 SushiSwap比较复杂,一方面是因为大多数的文档没有做到由浅入深地讲解,概念上没有注意先后顺序,给读者的理解带来困难

详解 SushiSwap

  • Sushiswap
  • Uniswap V2

了解 SushiSwap 的实现细节

  • 原文:https://soliditydeveloper.com/sushi-swap
  • 译文出自:登链翻译计划
  • 译者:翻译小组
  • 校对:Tiny 熊
  • 本文永久链接:learnblockchain.cn/article…

你现在可能已经听说过SushiSwap了。其分叉自Uniswap,同时带来了新的功能,比如质押和治理。但它背后的合约究竟是如何运作的呢?

其实这并不难。详细了解这个工作原理将是学习Solidity和Defi的一个好方法。

合约细节

我们现在将深入SushiSwap的实现细节。为了更容易理解,一些代码被修改了。你可以随时查看Github里面的完整代码。

1. Uniswap v2

SushiSwap核心部分只是一个Uniswap v2的分叉。除了一些小的差别,合同代码是完全复制的。如果你对Uniswap v2的工作原理感到好奇,请看我以前的文章这里。在不久的将来对Uniswap v3的深入研究。

特别是SushiSwap正在利用流动性池代币(LP代币)。请查看https://uniswap.org/docs/v2/core-concepts/pools/ 在 LP 代币下的所有细节。从本质上讲,LP是用来接收在流动池中累积的按比例费用。你在一个流动池里提供流动性,并得到LP代币的回报。当资金池现在随着交易的进行收取费用时,它们会在交易时平均分配给所有LP持有人。当你销毁LP代币时,则将收到对应流动池中的资金份额和收集的费用。

SushiSwap对Uniswap代码做了两处修改:

  1. 在部署中调用了setFeeTo函数,费用接受者被设置为SushiMaker合约(见下文)。一旦费用接受者被设置,由于当前交易导致的LP 发行量增长的1/6将以LP代币的形式被铸成协议费用。由于Uniswap的交易费是0.3%,因此每笔交易的0.05%的费用将流向SushiMaker。
  2. 增加了一个迁移者功能(见下文SushiRoll)。

你可以看到Uniswap的核心合约和SushiSwap如何改变它们之间的全部差异这里。

2. SushiMaker

详解 SushiSwap

SushiMaker将从SushiSwap上交易的人那里接收LP代币。它主要由一个 convert 函数组成,它的作用如下:

  1. 销毁(Burn)掉提供的LP代币。其结果将是收到按比例的token0token1的数量。
  2. 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 函数。

  1. 获取池中两个代币的当前储备。
  2. 从储备金和被兑换的代币金额中计算出接收金额,减去费用。计算是基于x*y=k曲线。

一旦计算出金额,我们就可以进行兑换了。转换为SUSHI的最后一步将总是通过传递SUSHI代币地址来调用_swap函数,并将其发送到bar:

_swap(token, sushi, amountIn, bar)

就这样,把所有的LP代币转换成了SUSHI,所有转换后的SUSHI都被送到了SushiBar,见下一个合约:

3. SushiBar

详解 SushiSwap

在SushiBar内,人们可以带着SUSHI进入,得到xSUSHI,然后带着更多的SUSHI离开。请记住,所有来自SushiMaker的SUSHI都被送到这里。所以随着时间的推移,SushiBar会积累越来越多的SUSHI。

谁会收到这个SUSHI?

任何进入SushiBar的人。用户进入后会收到xSUSHI,这有点像Uniswap的LP代币。它们代表了SushiBar中SUSHI代币的所有权。

你收到的xSUSHI数量是你转移的SUSHI xSUSHI发行总量 / SUSHI的当前余额。因此,如果你发送10个SUSHI到已经有100个SUSHI和200个xSUSHI发行总量的SushiBar,你将收到10 200 / 100 = 20个xSUSHI。

function enter(uint256 _amount) external {   uint256 totalSushi = sushi.balanceOf(address(this));   uint256 totalShares = totalSupply();    uint256 mintAmount =       totalShares == 0 || totalSushi == 0       ? _amount       : _amount.mul(totalShares).div(totalSushi);    _mint(msg.sender, mintAmount);   sushi.transferFrom(     msg.sender,     address(this),     _amount   ); }

现在,当你再次离开时,你会得到你的同等份额的SUSHI的回报,它至少是你所付的钱,但考虑到SushiBar将随着时间的推移积累SUSHI,它应该比你最初投入的更多。

function leave(uint256 _share) external {     uint256 totalShares = totalSupply();     uint256 transferAmount = _share         .mul(sushi.balanceOf(address(this)))         .div(totalShares);      _burn(msg.sender, _share);     sushi.transfer(msg.sender, transferAmount); }

你收到的SUSHI数量是你转移的XSUSHI 当前的SUSHI余额/XSUSHI发行总量。因此,如果你发送20个xSUSHI到SushiBar,其中有100个SUSHI和200个xSUSHI发行总量,你将收到 20 100 / 200 = 10个SUSHI。

3. SushiToken

当然,还有SUSHI代币合约本身。它是一个普通的ERC-20,具有与COMP代币相同的授权功能外,没有什么特别之处。我们之前已经讨论过COMP的治理。提到的Timelock合约也包含在SushiSwap中。

SUSHI代币允许将你的投票权委托给其他一些受信任的地址。这个地址就可以用增加的权力进行投票。任何时候你都可以选择重新委托给其他地址。

4. SushiRoll(Migrator)

在SushiRoll合约中提供了一个迁移器,帮助人们可以很容易地将流动性从Uniswap转移到SushiSwap。

通过迁移功能,可以完成:

  1. 从Uniswap中取出流动资金。
  2. 在SushiSwap中增加流动性。

代币对中任何可能剩余的代币都将返回给用户:

function migrate(     address tokenA,     address tokenB,     uint256 liquidity,     uint256 amountAMin,     uint256 amountBMin,     uint256 deadline ) external {     require(deadline >= block.timestamp, 'SushiSwap: EXPIRED');      // Remove liquidity from the old router with permit     (uint256 amountA, uint256 amountB) = removeLiquidity(         tokenA,         tokenB,         liquidity,         amountAMin,         amountBMin,         deadline     );      (uint256 pooledAmountA, uint256 pooledAmountB)         = addLiquidity(tokenA, tokenB, amountA, amountB);      if (amountA > pooledAmountA) {         IERC20(tokenA).safeTransfer(msg.sender, amountA - pooledAmountA);     }      if (amountB > pooledAmountB) {         IERC20(tokenB).safeTransfer(msg.sender, amountB - pooledAmountB);     } }

5. MasterChef

详解 SushiSwap

MasterChef实现了铸造新的SUSHI代币。这是创建SUSHI代币的唯一途径。它是通过在MasterChef内质押LP代币来实现铸币。MasterChef是由所有者控制的,这个所有者原来是Chef Nomi,但后来被属于9个人的多签钱包控制:

  • SBF_Alameda (FTX CEO)
  • Rleshner (Compound founder)
  • 0xMaki (Sushiswap总经理)
  • Lawmaster (The Block的研究主管)
  • CMsholdings (CMS控股公司)
  • Mattysino (Sino Global Capital的CEO)
  • mickhagen(Genesis Block founde)
  • AdamScochran(Cinneamhain Ventures的合伙人)
  • zippoxer (Zippo)

最终的计划是将MasterChef的控制权转移到治理上。所有者有权力控制资金池的分配点。流动性池的分配点越高,一个人在质押其LP代币时收到的SUSHI越多。在未来,这可能会产生强大的控制力,为参与特殊流动性池创造激励。

每个资金池可以获得的 SUSHI = 每区块生成的 SUSHI * 资金池的分配点 / 分配点总和

所有者可以通过add函数控制资金池的sushi分配点:

function add(uint256 _allocPoint, IERC20 _lpToken, bool _withUpdate) public onlyOwner;

updatePool

使用updatePool也可以更新当前的资金池,更新向质押LP代币的人铸造的SUSHI。

每个资金池新造的SUSHI数量取决于自上次更新以来生成区块数量和该资金池的设定分配点。在下边的例子中,为了简单起见,加上一些额外的乘数。

计算出的sushiReward将以10%的比例分配给开发者地址,其他90%分配给LP质押者.

function updatePool(uint256 _pid) public {     PoolInfo storage pool = poolInfo[_pid];     if (block.number <= pool.lastRewardBlock) {         return;     }     uint256 lpSupply = pool.lpToken.balanceOf(address(this));     if (lpSupply == 0) {         pool.lastRewardBlock = block.number;         return;     }      uint256 sushiReward = sushiPerBlock         .mul(pool.allocPoint)         .div(totalAllocPoint);      sushi.mint(devaddr, sushiReward.div(10));     sushi.mint(address(this), sushiReward);      pool.accSushiPerShare = pool.accSushiPerShare.add(         sushiReward.mul(1e12).div(lpSupply)     );     pool.lastRewardBlock = block.number; }

deposit

使用存款功能,用户可以将他们的LP代币抵押进相应的资金池。使用户的LP代币进入MasterChef合约:

function deposit(uint256 _pid, uint256 _amount) public {     PoolInfo storage pool = poolInfo[_pid];     UserInfo storage user = userInfo[_pid][msg.sender];     updatePool(_pid);     if (user.amount > 0) {         uint256 pending = user.amount                 .mul(pool.accSushiPerShare)                 .div(1e12)                 .sub(user.rewardDebt);         safeSushiTransfer(msg.sender, pending);     }      pool.lpToken.safeTransferFrom(         address(msg.sender),         address(this),         _amount     );      user.amount = user.amount.add(_amount);     user.rewardDebt = user.amount         .mul(pool.accSushiPerShare)         .div(1e12); }

withdraw

使用赎回功能,用户可以从资金池中将他们的LP代币赎回,他们将收获:

  1. 收到他们原来的LP代币
  2. 获得他们那份新铸造的SUSHI代币

铸币SUSHI的数量取决于之前计算的accSushiPerShare (见updatePool), accSushiPerShare 表示为每份额存款的累加的 SUSHI 收益:

function withdraw(uint256 _pid, uint256 _amount) public {     PoolInfo storage pool = poolInfo[_pid];     UserInfo storage user = userInfo[_pid][msg.sender];     require(user.amount >= _amount, "withdraw: not good");     updatePool(_pid);     uint256 pending =         user.amount             .mul(pool.accSushiPerShare)             .div(1e12)             .sub(user.rewardDebt);     safeSushiTransfer(msg.sender, pending);     user.amount = user.amount.sub(_amount);     user.rewardDebt = user.amount         .mul(pool.accSushiPerShare)         .div(1e12);     pool.lpToken.safeTransfer(address(msg.sender), _amount); }

本翻译由 Cell Network 赞助支持。

部分转自网络,侵权联系删除www.interchains.cchttps://www.interchains.cc/23054.html

区块链毕设网(www.interchains.cc)全网最靠谱的原创区块链毕设代做网站 部分资料来自网络,侵权联系删除! 最全最大的区块链源码站 ! QQ3039046426
区块链知识分享网, 以太坊dapp资源网, 区块链教程, fabric教程下载, 区块链书籍下载, 区块链资料下载, 区块链视频教程下载, 区块链基础教程, 区块链入门教程, 区块链资源 » 详解 SushiSwap

提供最优质的资源集合

立即查看 了解详情