|慢雾:DeFi 当红项目 YAM 闪电折戟,一行代码如何蒸发数亿美元?( 二 )


function afterRebase( uint256 mintAmount, uint256 offPegPerc ) internal { // update uniswap UniswapPair(uniswap_pair).sync; //SlowMist// 通过 uniswap 购买 yCRV 代币if (mintAmount > 0) { buyReserveAndTransfer( mintAmount, offPegPerc ); } // call any extra functions //SlowMist// 社区管理调用 for (uint i = 0; itransactions.length; i++) { Transaction storage t = transactions[i]; if (t.enabled) { bool result = externalCall(t.destination, t.data); if (!result) { emit TransactionFailed(t.destination, i, t.data); revert(''Transaction Failed''); } } } }通过分析发现 ,afterRebase 函数主要的逻辑在 buyReserveAndTransfer 函数中 , 此函数用于将增发出来的代币的一部分用于到 Uniswap 中购买 yCRV 代币 。 跟踪 buyReserveAndTransfer 函数 , 代码如下:
* function buyReserveAndTransfer( uint256 mintAmount, uint256 offPegPerc ) internal { UniswapPair pair = UniswapPair(uniswap_pair); YAMTokenInterface yam = YAMTokenInterface(yamAddress); // get reserves (uint256 token0Reserves, uint256 token1Reserves, ) = pair.getReserves; // check if protocol has excess yam in the reserve uint256 excess = yam.balanceOf(reservesContract); //SlowMist// 计算用于 Uniswap 中兑换的 YAM 数量 uint256 tokens_to_max_slippage = uniswapMaxSlippage(token0Reserves, token1Reserves, offPegPerc); UniVars memory uniVars = UniVars({ yamsToUni: tokens_to_max_slippage, // how many yams uniswap needs amountFromReserves: excess, // how much of yamsToUni comes from reserves mintToReserves: 0 // how much yams protocol mints to reserves }); // tries to sell all mint + excess // falls back to selling some of mint and all of excess // if all else fails, sells portion of excess // upon pair.swap, `uniswapV2Call` is called by the uniswap pair contract if (isToken0) { if (tokens_to_max_slippage > mintAmount.add(excess)) { // we already have performed a safemath check on mintAmount+excess // so we dont need to continue using it in this code path // can handle selling all of reserves and mint uint256 buyTokens = getAmountOut(mintAmount + excess, token0Reserves, token1Reserves); uniVars.yamsToUni = mintAmount + excess; uniVars.amountFromReserves = excess; // call swap using entire mint amount and excess; mint 0 to reserves pair.swap(0, buyTokens, address(this), abi.encode(uniVars)); } else { if (tokens_to_max_slippage > excess) { // uniswap can handle entire reserves uint256 buyTokens = getAmountOut(tokens_to_max_slippage, token0Reserves, token1Reserves); // swap up to slippage limit, taking entire yam reserves, and minting part of total //SlowMist// 将多余代币铸给 reserves 合约 uniVars.mintToReserves = mintAmount.sub((tokens_to_max_slippage - excess)); //SlowMist// Uniswap 代币交换 pair.swap(0, buyTokens, address(this), abi.encode(uniVars)); } else { // uniswap cant handle all of excess uint256 buyTokens = getAmountOut(tokens_to_max_slippage, token0Reserves, token1Reserves); uniVars.amountFromReserves = tokens_to_max_slippage; uniVars.mintToReserves = mintAmount; // swap up to slippage limit, taking excess - remainingExcess from reserves, and minting full amount // to reserves pair.swap(0, buyTokens, address(this), abi.encode(uniVars)); } } } else { if (tokens_to_max_slippage > mintAmount.add(excess)) { // can handle all of reserves and mint uint256 buyTokens = getAmountOut(mintAmount + excess, token1Reserves, token0Reserves); uniVars.yamsToUni = mintAmount + excess; uniVars.amountFromReserves = excess; // call swap using entire mint amount and excess; mint 0 to reserves pair.swap(buyTokens, 0, address(this), abi.encode(uniVars)); } else { if (tokens_to_max_slippage > excess) { // uniswap can handle entire reserves uint256 buyTokens = getAmountOut(tokens_to_max_slippage, token1Reserves, token0Reserves); // swap up to slippage limit, taking entire yam reserves, and minting part of total //SlowMist// 增发的多余的代币给 reserves 合约 uniVars.mintToReserves = mintAmount.sub( (tokens_to_max_slippage - excess)); // swap up to slippage limit, taking entire yam reserves, and minting part of total //Slowist// 在 uniswap 中进行兑换 , 并最终调用 rebase 合约的 uniswapV2Call 函数 pair.swap(buyTokens, 0, address(this), abi.encode(uniVars)); } else { // uniswap cant handle all of excess uint256 buyTokens = getAmountOut(tokens_to_max_slippage, token1Reserves, token0Reserves); uniVars.amountFromReserves = tokens_to_max_slippage; uniVars.mintToReserves = mintAmount; // swap up to slippage limit, taking excess - remainingExcess from reserves, and minting full amount // to reserves pair.swap(buyTokens, 0, address(this), abi.encode(uniVars)); } } } }通过对代码分析 , buyReserveAndTransfer 首先会计算在 Uniswap 中用于兑换 yCRV 的 YAM 的数量 , 如果该数量少于 YAM 的铸币数量 , 则会将多余的增发的 YAM 币给 reserves 合约 , 这一步是通过 Uniswap 合约调用rebase合约的 uniswapV2Call 函数实现的 , 具体的代码如下:


推荐阅读