基于BSC测试网收益聚合器Beefy协议的编译、测试、部署

391 阅读4分钟

前言

文章主要介绍了收益聚合器Beefy协议在币安智能链测试网网上的编译测试部署流程,以Pancake上的USDC-BUSD最新Curve版流动池的农场质押为例,详细介绍了完整的操作流程。

准备工作

Node.js环境

nodejs.org/en/download…

WebStorm IDE

jetbra.in/5d84466e317…

beefy源码

github.com/beefyfinanc…

💡准备工作不做任何科普,关键链接已经写明,请自行折腾。

Beefy工程简介

本教程用到的目录有如下几个

  • contracts
  • scripts
  • test

contracts

这个目录下是所有的Beefy合约,当前还在使用的是BIFI目录下的合约,下面简要介绍一下子目录。

infra

这个目录下的合约为基础合约,提供一些基础功能,比如手续费控制等.

文章用到的有

BeefyFeeConfigurator.sol手续费设置合约

strategies

策略合约目录

文章用到的有

Curve/StrategyChefCurveLP.sol 使用Curve实现的流动性池策略合约

utils

工具合约目录

文章用到的有

GasFeeThrottler.sol Gas费限制器合约

GasPrice.sol Gas费限制配置合约

vaults

金库合约目录

文章用到的有

BeefyVaultV6.sol V6版的金库合约

scripts

infra

基础合约的部署脚本

文章用到的有

deploy-gasPrice.js 部署手续费限制器合约

deployFeeConfigurator.ts 部署手续费设置合约的可升级合约(ERC967)

vault

金库合约的部署脚本

此处没有我们需要的最新的基于Curve的StableLP的金库合约部署模板,需要自行编写,下文会有详细的代码。

Hardhat配置

作者是区块链的小白,hardhat也是这几天才接触,有说的不对的请大家指正。

Hardhat安装

自行搜索

Hardhat配置

hardhat.config.ts

这个配置文件中我们需要关注的部分,一个是bsc测试网的支持,一个是用到的账户的配置

bsc测试网是在config对象的networks属性下添加,例如:

const config: DeploymentConfig = {
  defaultNetwork: "bsctest",
  networks: {
    bsctest: {
      url: "https://data-seed-prebsc-1-s3.binance.org:8545",
      chainId: 97,
      gasLimit: 20000000,
      gas: 3000000000000000,
      gasPrice: 10000000000,
      accounts,
    },
  }
}

💡其中gasPrice是因为GasPrice.sol中的限制而取的最大值。

RPC的列表可以在这个链接检索

chainlist.org/chain/97

选Latency最小的即可

dafaultNetwork设置为bsctest可以让你在后续执行命令式无需手动指定bsctest

此时我们把目光移到

const accounts = getPKs();

这一行,这行是获取到项目用到的账号,打开getPKs()的方法体我们看到系统是读取了四个环境变量,因此我们需要在项目的根目录新增一个 .env文件,用以保存我们用到的账号,格式如下:

DEPLOYER_PK="Your Private Key Without 0x Prefix"
KEEPER_PK="Your Private Key Without 0x Prefix"
UPGRADER_PK="Your Private Key Without 0x Prefix"
REWARDER_PK="Your Private Key Without 0x Prefix"

部署顺序

GasPrice配置合约

hardhat run scripts/infra/deploy-gasPrice.js --network bsctest 

部署完毕后得到GasPrice合约的地址A1.

BeefyFeeConfigurator手续费配置合约

hardhat run scripts/infra/deployFeeConfigurator.ts --network bsctest

金库策略合约部署

部署之前要修改合约及关联合约中的几处变量

GasFeeThrottler.sol

address public gasprice = address(0x4548b3B8257E634Dd6cc91D1e94d29838Baf37ef);
修改为
address public gasprice = address(A1);//GasPrice合约部署后的地址

下面是deploy-chef-curve-strat.ts的源码

import hardhat, { ethers, web3 } from "hardhat";
import { addressBook } from "blockchain-addressbook";
import { predictAddresses } from "../../utils/predictAddresses";
import { setPendingRewardsFunctionName } from "../../utils/setPendingRewardsFunctionName";
import { verifyContract } from "../../utils/verifyContract";
const registerSubsidy = require("../../utils/registerSubsidy");

const CAKE = '0xFa60D973F7642B748046464e165A65B7323b0DEE'.toLowerCase();
const WBNB = '0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd'.toLowerCase();
const BUSD = '0x8516Fc284AEEaa0374E66037BD2309349FF728eA'.toLowerCase();
const shouldVerifyOnEtherscan = false;
const shouldTransferVaultOwnership = false;

const want = web3.utils.toChecksumAddress("0x1a77c359d0019cd8f4d36b7cdf5a88043d801072");
const vaultParams = {
  mooName: "Moo CakeV2 USDC-BUSD",
  mooSymbol: "mooCakeV2USDC-BUSD",
  delay: 21600,
};
const strategyParamsTestnet = {
  want: "0xb98C30fA9f5e9cf6749B7021b4DDc0DBFe73b73e",
  poolId: 3,
  chef: "0xB4A466911556e39210a6bB2FaECBB59E4eB7E43d",
  pool: "0xb98C30fA9f5e9cf6749B7021b4DDc0DBFe73b73e",
  poolSize: 2,
  depositIndex: 1,
  useMetapool: false,
  unirouter: "0xD99D1c33F9fC3444f8101754aBC46c52416550D1",
  strategist: process.env.STRATEGIST_ADDRESS,
  keeper: process.env.KEEPER_ADDRESS,
  beefyFeeRecipient: process.env.FEE_RECIPIENT_ADDRESS,
  beefyFeeConfig: process.env.FEE_CONFIG_ADDRESS,
  outputToNativeRoute: [CAKE, WBNB],
  outputToDepositRoute: [CAKE, BUSD],
  shouldSetPendingRewardsFunctionName: false,
  pendingRewardsFunctionName: "pendingCake",
};

const contractNames = {
  vault: "BeefyVaultV6",
  strategy: "StrategyChefCurveLP",
};

async function main() {
  if (
    Object.values(vaultParams).some(v => v === undefined) ||
    Object.values(strategyParams).some(v => v === undefined) ||
    Object.values(contractNames).some(v => v === undefined)
  ) {
    console.error("one of config values undefined");
    return;
  }

  await hardhat.run("compile");

  const Vault = await ethers.getContractFactory(contractNames.vault);
  const Strategy = await ethers.getContractFactory(contractNames.strategy);

  const [deployer] = await ethers.getSigners();

  console.log("deployer:", deployer.address);
  console.log("Deploying:", vaultParams.mooName);

  const predictedAddresses = await predictAddresses({ creator: deployer.address });

  console.log("predictedAddresses :", predictedAddresses);

  const vaultConstructorArguments = [
    predictedAddresses.strategy,
    vaultParams.mooName,
    vaultParams.mooSymbol,
    vaultParams.delay,
  ];

  console.log("Deploying Vault :");
  const vault = await Vault.deploy(...vaultConstructorArguments);
  await vault.deployed();
  console.log("Deployed Vault!", vault.address);

  const strategyConstructorArguments = [
    strategyParamsTestnet.want,
    strategyParamsTestnet.poolId,
    strategyParamsTestnet.chef,
    strategyParamsTestnet.pool,
    strategyParamsTestnet.poolSize,
    strategyParamsTestnet.depositIndex,
    strategyParamsTestnet.useMetapool,
    strategyParamsTestnet.outputToNativeRoute,
    strategyParamsTestnet.outputToDepositRoute,
    [
      vault.address,
      strategyParamsTestnet.unirouter,
      strategyParamsTestnet.keeper,
      strategyParamsTestnet.strategist,
      strategyParamsTestnet.beefyFeeRecipient,
      strategyParamsTestnet.beefyFeeConfig,
    ],
  ];
  console.log("Deploying Strategy :");
  const override = { gasLimit: 20000000 };
  const strategy = await Strategy.deploy(...strategyConstructorArguments, override);
  await strategy.deployed();
  console.log("Deployed Strategy!", strategy.address);
  // add this info to PR
  console.log();
  console.log("Vault:", vault.address);
  console.log("Strategy:", strategy.address);
  console.log("Want:", strategyParams.want);
  console.log("PoolId:", strategyParams.poolId);

  console.log();
  console.log("Running post deployment");

  const verifyContractsPromises: Promise<any>[] = [];
  if (shouldVerifyOnEtherscan) {
    // skip await as this is a long running operation, and you can do other stuff to prepare vault while this finishes
    verifyContractsPromises.push(
      verifyContract(vault.address, vaultConstructorArguments),
      verifyContract(strategy.address, strategyConstructorArguments)
    );
  }

  if (strategyParams.shouldSetPendingRewardsFunctionName) {
    console.log("Set PendingRewards Function Name...");
    await setPendingRewardsFunctionName(strategy, strategyParams.pendingRewardsFunctionName);
    console.log("Set done!");
    console.log();
  }
  if (shouldTransferVaultOwnership) {
    console.log(`Transfering Vault Owner to ${process.env.VAULT_OWNER_ADDRESS}`)
    await vault.transferOwnership(beefyfinance.vaultOwner);
    console.log();
  }
  await Promise.all(verifyContractsPromises);

  if (hardhat.network.name === "bsc") {
    await registerSubsidy(vault.address, deployer);
    await registerSubsidy(strategy.address, deployer);
  }
}

main()
  .then(() => process.exit(0))
  .catch(error => {
    console.error(error);
    process.exit(1);
  });

执行脚本部署合约

hardhat run scripts/vault/deploy-chef-curve-strat.ts --network bsctest

❗此处有很多坑等我慢慢补充

TBD