Procedure Q

This section is the reference documentation for the procedures of ChainRunner Q. We will assume the account on the following procedures is the connected wallet, unless stated otherwise

Q.erc20

  • Defines the procedure for ERC20 tokens

Q.erc20.balanceOf

  • Returns the balance of ERC20 token in the connected wallet

  • Find the balance of USDT, USDC, LINK, DAI, BFC, BiFi

  proc erc20 () {
    proc balanceOf (tokenName) {
      let (account, _) = env.account.get ();
      return erc20.balanceOf (tokenName, account);
    }
  }

Q.bifi

  • Defines the procedure for BiFi

Q.bifi.isAssetNameCoin

  • Returns the state of the asset name as Ether or BNB

    proc isAssetNameCoin (assetName) {
      return assetName == "ether" || assetName == "eth" || assetName == "bnb";
    }

Q.bifi.getMaxWithdrawAmount

  • Returns the maximum amount of the asset available for withdraw

    proc getMaxWithdrawAmount (assetName) {
      let (account, _) = env.account.get ();
      if (isAssetNameCoin (assetName)) {
        let amount = bifi.eth.getUserMaxWithdrawAmount (account);
        return numToCurrency (amount, assetName, 18);
      } else {
        let amount = bifi.token.getUserMaxWithdrawAmount (assetName, account);
        let assetDeployment = erc20.getTokenContract (assetName);
        return numToCurrency (
          amount,
          assetDeployment.symbol (),
          assetDeployment.decimals ()
        );
      }
    }

Q.bifi.getMaxBorrowAmount

  • Returns the maximum amount of the asset available for borrow

    proc getMaxBorrowAmount (assetName) {
      let (account, _) = env.account.get ();
      if (isAssetNameCoin (assetName)) {
        let amount = bifi.eth.getUserMaxBorrowAmount (account);
        return numToCurrency (amount, assetName, 18);
      } else {
        let amount = bifi.token.getUserMaxBorrowAmount (assetName, account);
        let assetDeployment = erc20.getTokenContract (assetName);
        return numToCurrency (
          amount,
          assetDeployment.symbol (),
          assetDeployment.decimals ()
        );
      }
    }

Q.bifi.getMaxRepayAmount

  • Returns the maximum amount of the asset available for repay

    proc getMaxRepayAmount (assetName) {
      let (account, _) = env.account.get ();
      if (isAssetNameCoin (assetName)) {
        let amount = bifi.eth.getUserMaxRepayAmount (account);
        return numToCurrency (amount, assetName, 18);
      } else {
        let amount = bifi.token.getUserMaxRepayAmount (assetName, account);
        let assetDeployment = erc20.getTokenContract (assetName);
        return numToCurrency (
          amount,
          assetDeployment.symbol (),
          assetDeployment.decimals ()
        );
      }
    }

Q.bifi.deposit

  • Deposits the asset

    proc deposit (assetName, amount) {
      if (isAssetNameCoin (assetName)) {
        bifi.eth.deposit (amount);
      } else {
        bifi.token.deposit (assetName, amount);
      }
    }

Q.bifi.withdraw

  • Withdraws the asset

    proc withdraw (assetName, amount) {
      if (isAssetNameCoin (assetName)) {
        bifi.eth.withdraw (amount);
      } else {
        bifi.token.withdraw (assetName, amount);
      }
    }

Q.bifi.borrow

  • Borrows the asset

    proc borrow (assetName, amount) {
      if (isAssetNameCoin (assetName)) {
        bifi.eth.borrow (amount);
      } else {
        bifi.token.borrow (assetName, amount);
      }
    }

Q.bifi.repay

  • Repays the asset

    proc repay (assetName, amount) {
      if (isAssetNameCoin (assetName)) {
        bifi.eth.repay (amount);
      } else {
        bifi.token.repay (assetName, amount);
      }
    }

Q.bifi.depositLp

  • Deposits token/WETH LP to BiFi

    proc depositLp (tokenName, amount) {
      let modelAddr = bifi.lpStake.getModelAddr (tokenName);
      let model = bifi.lpStake.getModel (tokenName);
      let lpAddr = Q.sushi.getWETHTokenLpAddr (tokenName);
      erc20.approve (lpAddr, modelAddr, amount);
      model.deposit (amount);
    }

Q.bifiX

  • Defines the procedure for BiFi X

Q.bifiX.getFee

  • Returns the BiFi token fee for using BiFi-X

    proc getFee () {
      let (account, _) = env.account.get ();
      let fee = bifiX.callProxy.getFee (account);
      return numToCurrency (fee, "bifi", 18);
    }

Q.bifiX.getPositionAddr

  • Returns the address of the most recent position created on BiFi-X

    proc getPositionAddr () {
      let (account, _) = env.account.get ();
      let positions = bifiX.callProxy.getAllPositionStatus (account);
      let positionCount = positions.length ();
      if (positionCount == 0) { return ""; }
      let (_, positionAddr, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) = positions[positionCount - 1];
      return positionAddr;
    }

Q.bifix.getPositionDepositBorrowAmount

    proc getPositionDepositBorrowAmount (assetName, positionAddr) {
      if (assetName == "ether") {
        let (depositAmount, borrowAmount) = bifi.eth.getUserAmount (positionAddr);
        let depositAmount = numToCurrency (depositAmount, "ether", 18);
        let borrowAmount = numToCurrency (borrowAmount, "ether", 18);
        return (depositAmount, borrowAmount);
      } else {
        let (depositAmount, borrowAmount) = bifi.token.getUserAmount (assetName, positionAddr);
        let assetDecimal = erc20.getDecimal (assetName);
        let depositAmount = numToCurrency (depositAmount, assetName, assetDecimal);
        let borrowAmount = numToCurrency (borrowAmount, assetName, assetDecimal);
        return (depositAmount, borrowAmount);
      }
    }

Q.bifiX.getMaxBoost

  • Returns the maximum Boost level (leverage position) when creating an Earn position

  • The Boost level must be set as less than or equal to the above value

    proc getMaxBoost (assetName) {
      if (assetName == "ether") {
        let coinHandler = bifi.getCoinHandlerProxy ();
        let coinHandlerID = coinHandler.getHandlerID ();
        return bifiX.callProxy.getMaxBoost (coinHandlerID);
      } else {
        let tokenHandler = bifi.getTokenHandlerProxy (assetName);
        let tokenHandlerID = tokenHandler.getHandlerID ();
        return bifiX.callProxy.getMaxBoost (tokenHandlerID);
      }
    }

Q.bifiX.createEarnPosition

  • Creates an Earn position on BiFi-X

    proc createEarnPosition (assetName, assetAmount, times) {
      let (account, _) = env.account.get ();
      let bifiAmount = Q.erc20.balanceOf ("bifi");
      // Get Earn position information
      let bifiDeciamlsAssetAmount = bifi.decimals.toBiFiDecimal (assetName, currencyToNum (assetAmount));
      let (_, _, collateralAmount, expectedDepositAmount, expectedBorrowAmount, _, _, _, flashloanFee, _, _, _, _) =
        bifiX.getStartPosition (assetName, bifiDeciamlsAssetAmount, times, account, bifiAmount);

      if (assetName == "ether") {
        let ethAddr = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
        let tokenAddr = [ethAddr];
        let coinHandler = bifi.getCoinHandlerProxy ();
        let coinHandlerID = coinHandler.getHandlerID ();
        let handlersAddress = [coinHandler.getAddress ()];
        let handlerIDs = [coinHandlerID];
        let fees = [flashloanFee, 0];
        let flashloanAmount = expectedDepositAmount - collateralAmount;
        let amounts = [collateralAmount, expectedBorrowAmount, flashloanAmount];
        let decimal = [10 ** 18, 10 ** 18];
        bifiX.xFactory.create
          (flashloanFee + collateralAmount, 1, tokenAddr, handlersAddress, handlerIDs, fees, amounts, decimal);
      } else {
        let tokenAddr = [erc20.getTokenAddr (assetName)];
        let tokenDecimal = erc20.getDecimal (assetName);
        let tokenHandler = bifi.getTokenHandlerProxy (assetName);
        let tokenHandlerID = tokenHandler.getHandlerID ();
        let handlersAddress = [tokenHandler.getAddress ()];
        let handlerIDs = [tokenHandlerID];
        let fees = [flashloanFee, 0];
        let flashloanAmount = expectedDepositAmount - collateralAmount;
        let amounts = [collateralAmount, expectedBorrowAmount, flashloanAmount];
        let decimal = [10 ** tokenDecimal, 10 ** tokenDecimal];
        bifiX.xFactory.create (0, 1, tokenAddr, handlersAddress, handlerIDs, fees, amounts, decimal);
      }
    }

Q.bifiX.approveBiFi

  • Approves BiFi-X to use BiFi tokens in the connected wallet

  • The 256-bit unsigned integer max amount will be approved to use when approving for the first time

    // Approve XFactory contract to take BiFi that will be paid for the fee charged from BiFi-X
    proc approveBiFi (bifiFee) {
      let (account, _) = env.account.get ();
      let bifiTokenAddr = erc20.getTokenAddr ("bifi");
      let xFactoryAddr = bifiX.xFactory.getAddress ();
      erc20.approve (bifiTokenAddr, xFactoryAddr, bifiFee);
    }
  }

Q.sushi

  • Defines the procedure for SushiSwap

Q.sushi.getWETHTokenLpAddr

  • Returns the token address of the WETH/token pool

    proc getWETHTokenLpAddr (tokenName) {
      let wethAddr = sushiswapV2.router02.getWethAddress ();
      let tokenAddr = erc20.getTokenAddr (tokenName);
      return sushiswapV2.factory.getPair (wethAddr, tokenAddr);
    }

Q.sushi.getWETHLPBalance

  • Returns the token balance of WETH/token pool

    proc getWETHLpBalance (tokenName) {
      let (account, _) = env.account.get ();
      let lpAddr = getWETHTokenLpAddr (tokenName);
      return erc20.balanceOfByAddr (lpAddr, account);
    }

Q.sushi.getDefaultSlippage

  • Returns the default slippage on SushiSwap

  • The default slippage on SushiSwap is 0.5%

    // Returns default slippage(0.5%) on Sushiswap
    proc getDefaultSlippage () {
      return 0.5;
    }

Q.sushi.getAmountsOutFromExactIn

  • Returns the amount of specified ERC20 token that can be swapped from the specified amount of ERC20 token on SushiSwap

  • The default slippage on SushiSwap is 0.5%

    proc getAmountsOutFromExactIn (tokenName, amountIn) {
      let tokenAddr = erc20.getTokenAddr (tokenName);
      let path = [sushiswapV2.router02.getWethAddress(), tokenAddr];
      let results = sushiswapV2.router02.getAmountsOut (amountIn, path);
      let tokenDecimal = erc20.getDecimal (tokenName);
      return numToCurrency (results[1], tokenName, tokenDecimal);
    }

Q.sushi.swapExactETHForTokens

  • Swaps the specified amount of ETH to the specified ERC20 token on SushiSwap

  • The default slippage on SushiSwap is 0.5%

    proc swapExactETHForTokens (tokenName, amountIn) {
      let (account, _) = env.account.get ();
      let tokenAddr = erc20.getTokenAddr (tokenName);
      let path = [sushiswapV2.router02.getWethAddress(), tokenAddr];
      let amountOut = getAmountsOutFromExactIn (tokenName, amountIn);
      let tokenDecimal = erc20.getDecimal (tokenName);
      let slippage = getDefaultSlippage ();
      let amountOutMin = numToCurrency (amountOut, tokenName, tokenDecimal) * (1 - slippage / 100);
      let deadline = 2147483647;
      let tokenBalanceBefore = Q.erc20.balanceOf (tokenName);
      sushiswapV2.router02.swapExactETHForTokens(amountIn, amountOutMin, path, account, deadline);
      let tokenBalanceAfter = Q.erc20.balanceOf (tokenName);
      return tokenBalanceAfter - tokenBalanceBefore;
    }

Q.sushi.swapExactBNBForTokens

  • Swaps the specified amount of BNB to the specified ERC20 token on SushiSwap

  • The default slippage on SushiSwap is 0.5%

    proc swapExactBNBForTokens (tokenName, amountIn) {
      let (account, _) = env.account.get ();
      let tokenAddr = erc20.getTokenAddr (tokenName);
      let path = [sushiswapV2.router02.getWethAddress(), tokenAddr];
      let amountOut = getAmountsOutFromExactIn (tokenName, amountIn);
      let tokenDecimal = erc20.getDecimal (tokenName);
      let slippage = getDefaultSlippage ();
      let amountOutMin = numToCurrency (amountOut, tokenName, tokenDecimal) * (1 - slippage / 100);
      let deadline = 2147483647;
      sushiswapV2.router02.swapExactETHForTokens(amountIn, amountOutMin, path, account, deadline);
    }

Q.sushi.swapETHForExactTokens

  • Swaps ETH to the specified amount of specified ERC20 token on SushiSwap

  • The default slippage on SushiSwap is 0.5%

    proc swapETHForExactTokens (tokenName, amount) {
      let (account, _) = env.account.get ();
      let tokenAddr = erc20.getTokenAddr (tokenName);
      let path = [sushiswapV2.router02.getWethAddress(), tokenAddr];
      let result = sushiswapV2.router02.getAmountsIn(amount, path);
      let slippage = getDefaultSlippage ();
      let amountInMax = numToCurrency (result[0], "ether", 18) * (1 + slippage / 100);
      let deadline = 2147483647;
      sushiswapV2.router02.swapETHForExactTokens(amountInMax, amount, path, account, deadline);
    }

Q.sushi.addLiquidityETH

  • Adds liquidity to WETH/ERC20 pool on SushiSwap

  • The default slippage on SushiSwap is 0.5%

    proc addLiquidityETH (tokenName, amountTokenDesired, amountETHDesired) {
      let (account, _) = env.account.get ();
      let tokenAddr = erc20.getTokenAddr (tokenName);
      let tokenDecimal = erc20.getDecimals (tokenName);
      let routerAddr = sushiswapV2.router02.getAddress ();
      erc20.approve (tokenAddr, routerAddr, amountTokenDesired);

      let slippage = getDefaultSlippage ();
      let amountTokenMin = amountTokenDesired * (1 - slippage / 100);
      let amountETHMin = amountETHDesired * (1- slippage / 100);
      let deadline = 2147483647;

      let lpBalanceBefore = getWETHLpBalance (tokenName);

      sushiswapV2.router02.addLiquidityETH(
        tokenAddr,
        amountTokenDesired,
        amountETHDesired,
        amountTokenMin,
        amountETHMin,
        account,
        deadline
      );

      let lpBalanceAfter = getWETHLpBalance (tokenName);
      return lpBalanceAfter - lpBalanceBefore;
    }

Q.pancake

  • Defines the procedure for PancakeSwap

Q.pancake.getAmountOutFromExactIn

  • Returns the amount of tokens that will be received when swapping from BNB

    proc getAmountOutFromExactIn (tokenName, amountIn) {
      let tokenAddr = erc20.getTokenAddr (tokenName);
      let path = [pancakeSwap.router.getWethAddress (), tokenAddr];
      let results = pancakeSwap.router.getAmountsOut (amountIn, path);
      let tokenDecimal = erc20.getDecimal (tokenName);
      return numToCurrency (results[1], tokenName, tokenDecimal);
    }

Q.pancake.getDefaultSlippage

  • Returns the defaults slippages of PancakeSwap

    proc getDefaultSlippage () {
      return 0.5;
    }

Q.pancake.swapExactBNBForTokens

  • Returns the amount of the token swapped from the specified amount of BNB

    proc swapExactBNBForTokens (tokenName, amountIn) {
      let (account, _) = env.account.get ();
      let balanceBefore = erc20.balanceOf(tokenName, account);
      let tokenAddr = erc20.getTokenAddr (tokenName);
      let path = [pancakeSwap.router.getWethAddress (), tokenAddr];
      let amountOut = getAmountOutFromExactIn (tokenName, amountIn);
      let tokenDecimal = erc20.getDecimal (tokenName);
      let slippage = getDefaultSlippage ();
      let amountOutMin = numToCurrency (amountOut, tokenName, tokenDecimal) * (1 - slippage / 100);
      let deadline = 2 ** 31 - 1;
      pancakeSwap.router.swapExactETHForTokens(amountIn, amountOutMin, path, account, deadline);
      let balanceAfter = erc20.balanceOf(tokenName, account);
      return balanceAfter - balanceBefore;
    }

Q.pancake.addLiquidityBNB

  • Adds liquidity to the BNB and the specified token pool

    proc addLiquidityBNB (tokenName, amountBNBDesired, amountTokenDesired) {
      let (account, _) = env.account.get ();
      let tokenAddr = erc20.getTokenAddr (tokenName);
      let tokenDecimal = erc20.getDecimal (tokenName);
      let routerAddr = pancakeSwap.router.getAddress ();
      erc20.approve (tokenAddr, routerAddr, amountTokenDesired);

      let slippage = getDefaultSlippage ();
      let amountTokenMin = amountTokenDesired * (1 - slippage / 100);
      let amountBNBMin = amountBNBDesired * (1- slippage / 100);
      let deadline = 2 ** 31 - 1;
      pancakeSwap.router.addLiquidityETH(
        tokenAddr,
        amountTokenDesired,
        amountBNBDesired,
        amountTokenMin,
        amountBNBMin,
        account,
        deadline
      );
    }
  }

Q.compound

  • Defines the procedure for Compound

Q.compound.deposit

  • Deposits the asset

    proc deposit (assetName, amount) {
      if (assetName == "ether") {
        compound.cEther.mint(amount);
      } else {
        let assetAddr = erc20.getTokenAddr (assetName);
        let cTokenAddr = compound.cToken.getCTokenContractAddr (assetName);
        erc20.approve (assetAddr, cTokenAddr, amount);
        compound.cToken.mint(assetName, amount);
      }
    }

Q.compound.getUseReserveAsCollateral

  • Returns the state of the asset as collateral

    proc getUseReserveAsCollateral (assetName) {
      let (account, _) = env.account.get ();
      let cTokenAddr = compound.cToken.getCTokenContractAddr (assetName);
      for (addr in compound.comptroller.getAssetsIn (account)) {
        if (cTokenAddr == addr) {
          return true;
        }
      }
      return false;
    }

Q.compound.setUseReserveAsCollateral

  • Sets the state of the asset as collateral

    proc setUseReserveAsCollateral (assetName, useReserveAsCollateral) {
      let useReserveAsCollateralNow = getUseReserveAsCollateral (assetName);
      if (assetName == "ether") {
        let cETHAddr = compound.cEther.getCEtherAddr ();
        if (useReserveAsCollateral && !useReserveAsCollateralNow) {
          compound.comptroller.enterMarkets ([cETHAddr]);
        }
        if (!useReserveAsCollateral && useReserveAsCollateralNow) {
          compound.comptroller.exitMarket (cETHAddr);
        }
      } else {
        let cTokenAddr = compound.cToken.getCTokenContractAddr (assetName);
        if (useReserveAsCollateral && !useReserveAsCollateralNow) {
          compound.comptroller.enterMarkets ([cTokenAddr]);
        }
        if (!useReserveAsCollateral && useReserveAsCollateralNow) {
          compound.comptroller.exitMarket (cTokenAddr);
        }
      }
    }

Q.compound.getAvailableBorrows

  • Returns the amount of asset available for borrow

    proc getAvailableBorrows (assetName) {
      let (account, _) = env.account.get ();
      let (_, liquidity, _) = compound.comptroller.getAccountLiquidity (account);
      let liquidity = liquidity / 10 ** 18;

      if (assetName == "ether") {
        let cETHAddr = compound.cEther.getCEtherAddr ();
        let tokenPrice = compound.priceOracle.getUnderlyingPrice (cETHAddr) / 10 ** 18;
        let tokenAmount = (liquidity * 1.0) / tokenPrice;
        return numToCurrency (tokenAmount, assetName, 18);
      }

      let assetDeployment = erc20.getTokenContract (assetName);
      let assetDecimal = assetDeployment.decimals ();
      let assetSymbol = assetDeployment.symbol ();

      let cTokenAddr = compound.cToken.getCTokenContractAddr (assetName);
      let tokenPrice = compound.priceOracle.getUnderlyingPrice (cTokenAddr) / 10 ** (36 - assetDecimal);
      let tokenAmount = (liquidity * 1.0) / tokenPrice;

      if (assetDecimal > 18) {
        return numToCurrency (
          tokenAmount * 10 ** (assetDecimal - 18),
          assetSymbol,
          assetDecimal
        );
      }
      return
        numToCurrency (
          tokenAmount / 10 ** (18 - assetDecimal),
          assetSymbol,
          assetDecimal
        );
    }

Q.compound.borrow

  • Borrows the asset

    proc borrow (assetName, amount) {
      if (assetName == "ether") {
        compound.cEther.borrow (amount);
      } else {
        compound.cToken.borrow (assetName, amount);
      }
    }

Q.compound.getRepayAmount

  • Returns the amount of asset available for repay

    proc getRepayAmount (assetName) {
      let (account, _) = env.account.get ();
      if (assetName == "ether") {
        return compound.cEther.borrowBalanceCurrent (account);
      } else {
        return compound.cToken.borrowBalanceCurrent (assetName, account);
      }
    }

Q.compound.repay

  • Repays the asset

    proc repay (assetName, amount) {
      if (assetName == "ether") {
        compound.cEther.repayBorrow (amount);
      } else {
        let assetAddr = erc20.getTokenAddr (assetName);
        let cTokenAddr = compound.cToken.getCTokenContractAddr (assetName);
        erc20.approve (assetAddr, cTokenAddr, amount);
        compound.cToken.repayBorrow (assetName, amount);
      }
    }

Q.compound.getDepositAssetAmount

  • Returns the amount of asset deposited on Compound

    proc getDepositAssetAmount (assetName) {
      let (account, _) = env.account.get ();
      if (assetName == "ether") {
        let cETHAmount = compound.cEther.balanceOf (account);
        let ethAmount = cETHAmount * compound.cEther.exchangeRateCurrent () / 10 ** 18;
        return numToCurrency (ethAmount, "eth", 18);
      } else {
        let cTokenAmount = compound.cToken.balanceOf (assetName, account);
        let tokenAmount = cTokenAmount * compound.cToken.exchangeRateCurrent (assetName) / 10 ** 18;
        let tokenDecimal = erc20.getDecimal (assetName);
        return numToCurrency (tokenAmount, assetName, tokenDecimal);
      }
    }

Q.compound.withdraw

  • Withdraws the asset deposited on Compound

    proc withdraw (assetName, assetAmount) {
      if (assetName == "ether") {
        let cAssetAmount = assetAmount * 10 ** 18 / compound.cEther.exchangeRateCurrent ();
        compound.cEther.redeem (cAssetAmount);
      } else {
        let cAssetAmount = assetAmount * 10 ** 18 / compound.cToken.exchangeRateCurrent (assetName);
        compound.cToken.redeem (assetName, cAssetAmount);
      }
    }

Q.aaveV2

  • Defines the procedure for AAVE V2

  • Interest calulation modes for borrows and repays are as follows:

    • 1: stable

    • 2: variable

Q.aaveV2.getAssetAddr

  • Returns the asset token address

    proc getAssetAddr (assetName) {
      if (assetName == "ether") {
        return aaveV2.wethGateway.getWETHAddress ();
      } else {
        return erc20.getTokenAddr (assetName);
      }
    }

Q.aave.getUseReserveAsCollateral

  • Returns the state of the asset as collateral

    proc getUseReserveAsCollateral (assetName) {
      let assetAddr = getAssetAddr (assetName);
      let (account, _) = env.account.get ();
      let (_, _, _, _, _, _, _, _, useReserveAsCollateral) = aaveV2.aaveProtocolDataProvider.getUserReserveData (assetAddr, account);
      return useReserveAsCollateral;
    }

Q.aaveV2.setUseReserveAsCollateral

  • Sets the state of the asset as collateral

    proc setUseReserveAsCollateral (assetName, useReserveAsCollateral) {
      if (useReserveAsCollateral == getUseReserveAsCollateral (assetName)) {
        return ();
      }

      let assetAddr = getAssetAddr (assetName);
      aaveV2.lendingPool.setUserUseReserveAsCollateral (assetAddr, useReserveAsCollateral);
    }

Q.aaveV2.getAmountWithdrawMax

  • Returns the maximum amount of the asset available for withdraw

    proc getAmountWithdrawMax (assetName) {
      return getUserReserve (assetName);
    }

Q.aaveV2.getAmountBorrowMax

  • Returns the maximum amount of the asset available for borrow

    proc getAmountBorrowMax (assetName) {
      let (account, _) = env.account.get ();
      let (_, _, availableBorrowsETH, _, _, _) = aaveV2.lendingPool.getUserAccountData(account);
      if (assetName == "ether") {
        return numToCurrency(availableBorrowsETH, "ether", 18);
      }

      let assetAddr = erc20.getTokenAddr (assetName);
      let assetPriceETH = aaveV2.aaveOracle.getAssetPrice (assetAddr);

      let availableBorrows = availableBorrowsETH * 1.0 / assetPriceETH;
      let assetDeployment = erc20.getTokenContract(assetName);
      let assetDecimals = assetDeployment.decimals ();
      let assetSymbol = assetDeployment.symbol ();
      if (assetDecimals > 18) {
        return numToCurrency (
          availableBorrows * 10 ** (assetDecimals - 18),
          assetSymbol,
          assetDecimals
        );
      }

      return numToCurrency (
        availableBorrows / 10 ** (18 - assetDecimals),
        assetSymbol,
        assetDecimals
      );
    }

Q.aaveV2.getAmountRepayMax

  • Returns the maximum amount of the asset available for repay

    proc getAmountRepayMax (assetName, interestRateMode) {
      proc getDeptAmount (assetAddr, interestRateMode) {
        let (account, _) = env.account.get ();
        let (_, amountDeptStable, amountDeptVariable, _, _, _, _, _, _) =
        aaveV2.aaveProtocolDataProvider.getUserReserveData (assetAddr, account);
        if (interestRateMode == 1) {
          return amountDeptStable;
        } else {
          return amountDeptVariable;
        }
      }
      let assetAddr = getAssetAddr (assetName);
      let assetDeployment = reg (assetAddr, "/Prelude/ABI/ERC20.ABI.json");
      let amount = getDeptAmount (assetAddr, interestRateMode);

      if (assetName == "ether") {
        return numToCurrency (amount, assetName, 18);
      } else {
        return numToCurrency (amount, assetName, erc20.getDecimal (assetName));
      }
    }

Q.aaveV2.getUserReserve

  • Returns the amount of asset deposited

    proc getUserReserve (assetName) {
      let (account, _) = env.account.get ();
      if (assetName == "ether") {
        let wethAddr = aaveV2.wethGateway.getWETHAddress ();
        let (ethAmount, _, _, _, _, _, _, _, _) =
          aaveV2.aaveProtocolDataProvider.getUserReserveData (wethAddr, account);
        return numToCurrency(ethAmount, "ether", 18);
      } else {
        let assetAddr = erc20.getTokenAddr (assetName);
        let (assetAmount, _, _, _, _, _, _, _, _) =
          aaveV2.aaveProtocolDataProvider.getUserReserveData (assetAddr, account);
        let assetDecimal = erc20.getDecimal (assetName);
        return numToCurrency(assetAmount, assetName, assetDecimal);
      }
    }

Q.aaveV2.deposit

  • Deposits the asset

    proc deposit (assetName, amount) {
      let (account, _) = env.account.get ();
      if (assetName == "ether") {
        aaveV2.wethGateway.depositETH (amount, account, 0);
      } else {
        let assetAddr = erc20.getTokenAddr (assetName);
        let lendingPoolAddr = aaveV2.lendingPool.getAddress ();
        erc20.approve(assetAddr, lendingPoolAddr, amount);
        aaveV2.lendingPool.deposit (assetAddr, amount, account, 0);
      }
    }

Q.aaveV2.withdraw

  • Withdraws the asset

    proc withdraw (assetName, amount) {
      let (account, _) = env.account.get ();
      if (assetName == "ether") {
        aaveV2.wethGateway.withdrawETH (amount, account);
      } else {
        let assetAddr = erc20.getTokenAddr (assetName);
        aaveV2.lendingPool.withdraw (assetAddr, amount, account);
      }
    }

Q.aaveV2.borrow

  • Borrows the asset

    proc borrow (assetName, amount, interestRateMode) {
      let (account, _) = env.account.get ();
      if (assetName == "ether") {
        aaveV2.wethGateway.borrowETH (amount, interestRateMode, 0);
      } else {
        let assetAddr = erc20.getTokenAddr (assetName);
        aaveV2.lendingPool.borrow (assetAddr, amount, interestRateMode, 0, account);
      }
    }

Q.aaveV2.repay

  • Repays the asset

    proc repay (assetName, amount, interestRateMode) {
      let (account, _) = env.account.get ();
      if (assetName == "ether") {
        aaveV2.wethGateway.repayETH (amount, amount, interestRateMode, account);
      } else {
        let assetAddr = erc20.getTokenAddr (assetName);
        let lendingPoolAddr = aaveV2.lendingPool.getAddress ();
        erc20.approve(assetAddr, lendingPoolAddr, amount);
        aaveV2.lendingPool.repay (assetAddr, amount, interestRateMode, account);
      }
    }

Q.venus

  • Defines the procedure for Venus protocol

Q.venus.getReserve

  • Return the amount of asset deposited

    proc getReserve (assetName) {
      let (account, _) = env.account.get ();
      if (assetName == "bnb") {
        return venus.vBNB.balanceOfUnderlying (account);
      } else {
        let vBEP20Name = venus.getVTokenName (assetName);
        return venus.vBEP20.balanceOfUnderlying(vBEP20Name, account);
      }
    }

Q.venus.getAmountWithdrawMax

  • Return the maximum amount of the asset available for withdraw

    proc getAmountWithdrawMax (assetName) {
      return getReserve (assetName);
    }

Q.venus.getAmountBorrowMax

  • Returns the maximum amount of the asset available for borrow

    proc getAmountBorrowMax (assetName) {
      let (account, _) = env.account.get ();
      let (_, liquidityUSD18, _) =
        venus.comptroller.getAccountLiquidity (account);
      let vTokenName = venus.getVTokenName (assetName);
      let vTokenAddr = venus.getAddr (vTokenName);
      let vTokenPriceUSD18 = venus.priceOracle.getUnderlyingPrice (vTokenAddr);
      let vTokenAmount = (liquidityUSD18 * 1.0) / vTokenPriceUSD18;

      if (assetName == "bnb") {
        return numToCurrency (vTokenAmount, assetName, 18);
      }

      let assetDeployment = erc20.getTokenContract (assetName);
      let assetDecimal = assetDeployment.decimals ();
      let assetSymbol = assetDeployment.symbol ();
      if (assetDecimal > 18) {
        return numToCurrency (
          vTokenAmount * 10 ** (assetDecimal - 18),
          assetSymbol,
          assetDecimal
        );
      }
      return numToCurrency (
          vTokenAmount / 10 ** (18 - assetDecimal),
          assetSymbol,
          assetDecimal
      );
    }

Q.venus.getAmountRepayMax

  • Returns the maximum amount of the asset available for repay

    proc getAmountRepayMax (assetName) {
      let (account, _) = env.account.get ();
      if (assetName == "bnb") {
        return venus.vBNB.borrowBalanceCurrent (account);
      } else {
        let vBEP20Name = venus.getVTokenName (assetName);
        return venus.vBEP20.borrowBalanceCurrent (vBEP20Name, account);
      }
    }

Q.venus.deposit

  • Deposits the asset

    proc deposit (assetName, amount) {
      if (assetName == "bnb") {
        venus.vBNB.mint (amount);
      } else {
        let assetAddr = erc20.getTokenAddr (assetName);
        let vBEP20Name = venus.getVTokenName (assetName);
        let vBEP20Addr = venus.getAddr (vBEP20Name);
        erc20.approve (assetAddr, vBEP20Addr, amount);
        venus.vBEP20.mint (vBEP20Name, amount);
      }
    }

Q.venus.withdraw

  • Borrows the asset

    proc withdraw (assetName, amount) {
      if (assetName == "bnb") {
        venus.vBNB.redeemUnderlying (amount);
      } else {
        let vBEP20Name = venus.getVTokenName (assetName);
        venus.vBEP20.redeemUnderlying (vBEP20Name, amount);
      }
    }

Q.venus.borrow

  • Borrows the asset

    proc borrow (assetName, amount) {
      if (assetName == "bnb") {
        venus.vBNB.borrow (amount);
      } else {
        let vBEP20Name = venus.getVTokenName (assetName);
        venus.vBEP20.borrow (vBEP20Name, amount);
      }
    }

Q.venus.repay

  • Repays the asset

    proc repay (assetName, amount) {
      if (assetName == "bnb") {
        venus.vBNB.repay (amount);
      } else {
        let assetAddr = erc20.getTokenAddr (assetName);
        let vBEP20Name = venus.getVTokenName (assetName);
        let vBEP20Addr = venus.getAddr (vBEP20Name);
        erc20.approve (assetAddr, vBEP20Addr, amount);
        venus.vBEP20.repayBorrow (vBEP20Name, amount);
      }
    }

Q.venus.getUseReserveAsCollateral

  • Returns the state of the asset as collateral

    proc getUseReserveAsCollateral (assetName) {
      let (account, _) = env.account.get();
      let vTokenName = venus.getVTokenName (assetName);
      let vTokenAddr = venus.getAddr (vTokenName);
      for (addr in venus.comptroller.getAssetsIn (account)) {
        if (vTokenAddr == addr) {
          return true;
        }
      }
      return false;
    }

Q.venus.setUseReserveAsCollateral

  • Sets the state of the asset as collacteral

    proc setUseReserveAsCollateral (assetName, useReserveAsCollateral) {
      let useReserveAsCollateralNow = getUseReserveAsCollateral (assetName);
      let vBEP20Name = venus.getVTokenName (assetName);
      let vBEP20Addr = venus.getAddr (vBEP20Name);
      if (useReserveAsCollateral && !useReserveAsCollateralNow) {
        venus.comptroller.enterMarkets ([vBEP20Addr]);
        return ();
      }
      if (!useReserveAsCollateral && useReserveAsCollateralNow) {
        venus.comptroller.exitMarket(vBEP20Addr);
        return ();
      }
    }

Last updated