SUSHI的源码及方案解析二(智能合约部署补充)

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

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

SUSHI的源码及方案解析二(智能合约部署补充)是很好的区块链资料,他说明了区块链当中的经典原理,可以给我们提供资料,SUSHI的源码及方案解析二(智能合约部署补充)学习起来其实是很简单的,

不多的几个较为抽象的概念也很容易理解,之所以很多人感觉SUSHI的源码及方案解析二(智能合约部署补充)比较复杂,一方面是因为大多数的文档没有做到由浅入深地讲解,概念上没有注意先后顺序,给读者的理解带来困难

SUSHI的源码及方案解析二(智能合约部署补充)

  • 交易所
  • 智能合约

我在上一篇说的是早期流动性挖矿部分。我们观看真正的sushi合约,发现不单单是那两个sol文件,因此本节就对剩下的文件重点部分做一下补充。

首先说一下。我的开发项目是智能设备自治,其中有一个很关键的部分就是,物联网设备之前如何进行有价的信息交换。 我在上一篇说的是早期流动性挖矿部分。我们观看真正的sushi合约,发现不单单是那两个sol文件,因此本节就对剩下的文件重点部分做一下补充。由于相关的笔记都是半年前做的,比较混乱,所以大家仅做参考即可。

智能合约内容补充

正式的sushi合约分两部分,一部分是sushi本体,一部分是uniswap部分。因为uniswap有很多人都讲过,所以这里只讲sushi本体。 GovernorAlpha.sol涉及到治理; Migrations.sol涉及到部署; MockERC20.sol涉及到新LP的发布; SushiToken.sol顾名思义就是sushi自身代币的发布。 这些都比较简单,我们对下面几个文件做一下描述。

Timelock.sol

高权限功能的实现。 重点是executeTransaction函数:

    function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable returns (bytes memory) {         require(msg.sender == admin, "Timelock::executeTransaction: Call must come from admin.");          bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));         require(queuedTransactions[txHash], "Timelock::executeTransaction: Transaction hasn't been queued.");         require(getBlockTimestamp() >= eta, "Timelock::executeTransaction: Transaction hasn't surpassed time lock.");         require(getBlockTimestamp() <= eta.add(GRACE_PERIOD), "Timelock::executeTransaction: Transaction is stale.");          queuedTransactions[txHash] = false;          bytes memory callData;          if (bytes(signature).length == 0) {//可以理解为是一个签名为0             callData = data;         } else {             callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);//calldata为data地址         }          // solium-disable-next-line security/no-call-value         (bool success, bytes memory returnData) = target.call.value(value)(callData);//call函数转账的使用方法是:地址.call.value(转账金额)()         require(success, "Timelock::executeTransaction: Transaction execution reverted.");          emit ExecuteTransaction(txHash, target, value, signature, data, eta);          return returnData;     }

Migrator.sol

迁移

contract Migrator {     address public chef;     address public oldFactory;//因此这里面的oldFactory应该就是uniswap的factory     IUniswapV2Factory public factory;//应该是我们自己的新factory     uint256 public notBeforeBlock;     uint256 public desiredLiquidity = uint256(-1);     constructor(         address _chef,         address _oldFactory,         IUniswapV2Factory _factory,         uint256 _notBeforeBlock     ) public {         chef = _chef;         oldFactory = _oldFactory;         factory = _factory;         notBeforeBlock = _notBeforeBlock;     }      //chef里面的引用。     //IERC20 newLpToken = migrator.migrate(lpToken);//完成转移,用的是lpToken的factory     //简单说如果没有就是新建,如果有则chef获取所有的token0和1,然后挖出来的新的lp令牌     //最后进行令牌的更换(对于挖矿的人来说,换了一个流动资金池,这个资金池里面可以取出来lp,同时还存储令牌对应的token0和1)     //如果这个矿池被开发者控制则非常的危险。     function migrate(IUniswapV2Pair orig) public returns (IUniswapV2Pair) {         require(msg.sender == chef, "not from master chef");//发送者必须是chef         require(block.number >= notBeforeBlock, "too early to migrate");//迁移时间必须是大于这个值才行         require(orig.factory() == oldFactory, "not from old factory");//         address token0 = orig.token0();//然后将token0和1分别授权         address token1 = orig.token1();         IUniswapV2Pair pair = IUniswapV2Pair(factory.getPair(token0, token1));//引入一个我们自己factory的地址         if (pair == IUniswapV2Pair(address(0))) {             pair = IUniswapV2Pair(factory.createPair(token0, token1));//如果没有则新建         }         uint256 lp = orig.balanceOf(msg.sender);//获得信息发送者,也就是chef的所有令牌数量         if (lp == 0) return pair;//类似于新建         desiredLiquidity = lp;         orig.transferFrom(msg.sender, address(orig), lp);//将lp从chef里面发到旧的orig地址(意味着返回所有的token0和1到chef         orig.burn(address(pair));//烧掉所有在orig(旧的)的pair的lp         pair.mint(msg.sender);//挖新的lp到chef里面去         desiredLiquidity = uint256(-1);         return pair;//返回pair     } }

MasterChef.sol

    //这里主要涉及到一些基本的设定      function poolLength() external view returns (uint256) {         return poolInfo.length;     }      // Add a new lp to the pool. Can only be called by the owner.     // XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do.     //增加新币,管理员才可以     function add(uint256 _allocPoint, IERC20 _lpToken, bool _withUpdate) public onlyOwner {         if (_withUpdate) {             massUpdatePools();         }         uint256 lastRewardBlock = block.number > startBlock ? block.number : startBlock;         totalAllocPoint = totalAllocPoint.add(_allocPoint);         //下面这个是建立新的信息         poolInfo.push(PoolInfo({             lpToken: _lpToken,             allocPoint: _allocPoint,             lastRewardBlock: lastRewardBlock,             accSushiPerShare: 0         }));     }      // Update the given pool's SUSHI allocation point. Can only be called by the owner.     //设置池子的sushi点,管理员才行     function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner {         if (_withUpdate) {             massUpdatePools();         }         totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint);         poolInfo[_pid].allocPoint = _allocPoint;     }      // Set the migrator contract. Can only be called by the owner.     //设置迁移命令     function setMigrator(IMigratorChef _migrator) public onlyOwner {         migrator = _migrator;     }      // Migrate lp token to another lp contract. Can be called by anyone. We trust that migrator contract is good.     //令牌的迁移,说白了就是把在uniswap里面存的币转到chef里面,同时分新的令牌     //由于可以一个池子一个池子的转换,所以不用担心安全性,可以先测试一下再进行。     function migrate(uint256 _pid) public {         require(address(migrator) != address(0), "migrate: no migrator");         PoolInfo storage pool = poolInfo[_pid];//获得池子的id         IERC20 lpToken = pool.lpToken;//获得池子id对应的pl令牌地址         uint256 bal = lpToken.balanceOf(address(this));//获得这个令牌地址里面在这次池子所有的币         lpToken.safeApprove(address(migrator), bal);//对migrator进行一个安全的授权         IERC20 newLpToken = migrator.migrate(lpToken);//完成转移,用的是lpToken的factory         require(bal == newLpToken.balanceOf(address(this)), "migrate: bad");//这里需要做一个令牌数量的校验         pool.lpToken = newLpToken;     }      // Return reward multiplier over the given _from to _to block.     //得到每块的币量说明     function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) {         if (_to <= bonusEndBlock) {             return _to.sub(_from).mul(BONUS_MULTIPLIER);         } else if (_from >= bonusEndBlock) {             return _to.sub(_from);         } else {             return bonusEndBlock.sub(_from).mul(BONUS_MULTIPLIER).add(                 _to.sub(bonusEndBlock)             );         }     }      // View function to see pending SUSHIs on frontend.     //系统发送sushi到pool,谁都可以调用     function pendingSushi(uint256 _pid, address _user) external view returns (uint256) {         PoolInfo storage pool = poolInfo[_pid];         UserInfo storage user = userInfo[_pid][_user];//地址         uint256 accSushiPerShare = pool.accSushiPerShare;//地址的配额         uint256 lpSupply = pool.lpToken.balanceOf(address(this));//发送到这个地址的lp的总量(也就是分红池的lp)         if (block.number > pool.lastRewardBlock && lpSupply != 0) {//如果是没有刷新,则意味着有币             uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);             uint256 sushiReward = multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(totalAllocPoint);             accSushiPerShare = accSushiPerShare.add(sushiReward.mul(1e12).div(lpSupply));         }         //上面是做一个判断         return user.amount.mul(accSushiPerShare).div(1e12).sub(user.rewardDebt);     }      // Update reward vairables for all pools. Be careful of gas spending!     //更新参数,被add调用     function massUpdatePools() public {         uint256 length = poolInfo.length;         for (uint256 pid = 0; pid < length; ++pid) {             updatePool(pid);         }     }      // Update reward variables of the given pool to be up-to-date.     //更新参数,间接被add调用     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 multiplier = getMultiplier(pool.lastRewardBlock, block.number);         uint256 sushiReward = multiplier.mul(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 tokens to MasterChef for SUSHI allocation.     //放置lp,用户调用     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);         emit Deposit(msg.sender, _pid, _amount);     }      // Withdraw LP tokens from MasterChef.     //撤回lp,用户调用     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);         emit Withdraw(msg.sender, _pid, _amount);     }      // Withdraw without caring about rewards. EMERGENCY ONLY.     //一次性返回     function emergencyWithdraw(uint256 _pid) public {         PoolInfo storage pool = poolInfo[_pid];         UserInfo storage user = userInfo[_pid][msg.sender];         pool.lpToken.safeTransfer(address(msg.sender), user.amount);         emit EmergencyWithdraw(msg.sender, _pid, user.amount);         user.amount = 0;         user.rewardDebt = 0;     }

SushiBar.sol

// Enter the bar. Pay some SUSHIs. Earn some shares. //本质上是一个分红池,但没有看到分红去哪里了(eth) function enter(uint256 _amount) public {     uint256 totalSushi = sushi.balanceOf(address(this));//本地址里面的sushi总量     uint256 totalShares = totalSupply();//已经做出来的总量     if (totalShares == 0 || totalSushi == 0) {         _mint(msg.sender, _amount);     } else {         uint256 what = _amount.mul(totalShares).div(totalSushi);//简单说就是,放进去的越少,给的越多         _mint(msg.sender, what);     }     sushi.transferFrom(msg.sender, address(this), _amount);//挖出来发送过去 }  // Leave the bar. Claim back your SUSHIs. function leave(uint256 _share) public {     uint256 totalShares = totalSupply();     uint256 what = _share.mul(sushi.balanceOf(address(this))).div(totalShares);     _burn(msg.sender, _share);     sushi.transfer(msg.sender, what);//撤出的份额 }

SushiMaker.sol

contract SushiMaker {     using SafeMath for uint256;      IUniswapV2Factory public factory;     address public bar;     address public sushi;     address public weth;      //新的工厂地址,sushibar地址,sushi地址,weth地址     constructor(IUniswapV2Factory _factory, address _bar, address _sushi, address _weth) public {         factory = _factory;         sushi = _sushi;         bar = _bar;         weth = _weth;     }          //一直没太理解,但应该就是分红。     function convert(address token0, address token1) public {         // At least we try to make front-running harder to do.         require(msg.sender == tx.origin, "do not convert from contract");         //首先发送者必须是地址而不是合约         IUniswapV2Pair pair = IUniswapV2Pair(factory.getPair(token0, token1));         //获得两个token的pair         pair.transfer(address(pair), pair.balanceOf(address(this)));         //按照数量从本地址到pair地址         pair.burn(address(this));//将本地烧毁         uint256 wethAmount = _toWETH(token0) + _toWETH(token1);//简单说就是将一对pair换算为eth,如果是sushi,则直接传输到bar并返回0,并且下面也是0         //如果是weth,则传输到eth/sushi交易对,并返回数量。下面执行该数量。         //如果都不是,则看看下面有没有对应的pair,那么多?都是为了解决对应pair的ab问题。         //简单说如果是sushi/eth,则sushi传输到bar,eth传输到sushi/eth交易对。         _toSUSHI(wethAmount);//然后再转换为sushi。     }      function _toWETH(address token) internal returns (uint256) {         if (token == sushi) {//如何这个币是sushi,则直接传输到bar里面,             uint amount = IERC20(token).balanceOf(address(this));             IERC20(token).transfer(bar, amount);             return 0;         }//如果是sushi则返回         if (token == weth) {             uint amount = IERC20(token).balanceOf(address(this));             IERC20(token).transfer(factory.getPair(weth, sushi), amount);//如果是eth,则直接传输到eth/sushi交易对里面去。             return amount;         }//也就是说,如果是eth/sushi,则默认处理。         IUniswapV2Pair pair = IUniswapV2Pair(factory.getPair(token, weth));         if (address(pair) == address(0)) {//如果不存在这个交易对则返回。             return 0;         }         //如果都不是则继续往下走         (uint reserve0, uint reserve1,) = pair.getReserves();         address token0 = pair.token0();         (uint reserveIn, uint reserveOut) = token0 == token ? (reserve0, reserve1) : (reserve1, reserve0);         uint amountIn = IERC20(token).balanceOf(address(this));         uint amountInWithFee = amountIn.mul(997);         uint numerator = amountInWithFee.mul(reserveOut);         uint denominator = reserveIn.mul(1000).add(amountInWithFee);         uint amountOut = numerator / denominator;         (uint amount0Out, uint amount1Out) = token0 == token ? (uint(0), amountOut) : (amountOut, uint(0));         IERC20(token).transfer(address(pair), amountIn);//这个就是核心语句,将执行convert的人的token币传输到pair里面去。         pair.swap(amount0Out, amount1Out, factory.getPair(weth, sushi), new bytes(0));//完成一次token的交换         return amountOut;     }      function _toSUSHI(uint256 amountIn) internal {         IUniswapV2Pair pair = IUniswapV2Pair(factory.getPair(weth, sushi));         //获取eth/sushi交易对信息         (uint reserve0, uint reserve1,) = pair.getReserves();         address token0 = pair.token0();         (uint reserveIn, uint reserveOut) = token0 == weth ? (reserve0, reserve1) : (reserve1, reserve0);//获得两个token的价格比         uint amountInWithFee = amountIn.mul(997);//去掉税后的钱         uint numerator = amountInWithFee.mul(reserveOut);//乘以价格比         uint denominator = reserveIn.mul(1000).add(amountInWithFee);//另一个价格比         uint amountOut = numerator / denominator;         (uint amount0Out, uint amount1Out) = token0 == weth ? (uint(0), amountOut) : (amountOut, uint(0));         pair.swap(amount0Out, amount1Out, bar, new bytes(0));//交换bar里面的两个值。     } }

智能合约部署补充

UniswapV2Factory.solo:p 可以设置一个迁移权限,这个需要管理员完成 feeToSetter,migrator。 Uniswap最终就布置一个文件即可,UniswapV2Factory.sol,但估计中间会生成很多中间合约,记得保存。 这个需要布置,在后面的Factory用 代币合同,带有COMP / YAM投票功能。 (需要部署,第一级)SushiToken.sol里面没有constructoro:p (需要部署,第一级)Timelock.sol,构造函数:管理员(地址),延伸时间(2到30天) 来自Compound的治理功能 (需要部署,第二级)GovernorAlpha.sol构造函数:时间锁地址,SushiToken地址(SushiToken public sushi),guardian(监护人地址,可以跟管理员不是一个人) 存入LP代币以进行SUSHI farm (需要部署,第二级)[MasterChef]().sol构造函数:SushiToken地址,devaddr地址(治理员,跟前两个不是一个),sushiPerBlock(每块创建的寿司代币数量,40暂定)bonusEndBlock(块结束时间,区块号,在这个后面就开始变少了8643000),startBlock(开始块的时间,开始才出口,8623000) Ps:用户调用的就是这块,也就意味着收益都存在MasterChef里面。同时也就意味着,分红需要调用这个地址。o:p (需要部署,第二级)SushiBar:抵押SUSHI可获得更多SUSHI。 是一个erc20币,sushibar,简称xSUSHI,ERC20("SushiBar", "xSUSHI") 构造的时候需要填入SUSHI的地址。 (需要部署,第三级)SushiMaker:收集交易费,转换为SUSHI,然后发送到SushiBar。 构架器:bar是sushibar的地址,factory是uniswap的factory地址(因为在sol里面一直强调的是getpair,0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f),sushi是token的地址,-web:0xc778417E063141139Fce010982780140Aa0cD5Ab 我先是add(没有用true),默认0参数。

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

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

提供最优质的资源集合

立即查看 了解详情