UNPKG

@gooddollar/goodprotocol

Version:
749 lines (672 loc) 22.7 kB
/*** * deploy complete DAO for testing purposes. * for example run: * npx hardhat run scripts/test/localDaoDeploy.ts --network develop * then to test upgrade process locally run: * npx hardhat run scripts/upgradeToV2/upgradeToV2.ts --network develop */ import { network, ethers, upgrades } from "hardhat"; import { Contract } from "ethers"; import DAOCreatorABI from "@gooddollar/goodcontracts/build/contracts/DaoCreatorGoodDollar.json"; import IdentityABI from "@gooddollar/goodcontracts/build/contracts/Identity.json"; import FeeFormulaABI from "@gooddollar/goodcontracts/build/contracts/FeeFormula.json"; import AddFoundersABI from "@gooddollar/goodcontracts/build/contracts/AddFoundersGoodDollar.json"; import ContributionCalculation from "@gooddollar/goodcontracts/stakingModel/build/contracts/ContributionCalculation.json"; import FirstClaimPool from "@gooddollar/goodcontracts/stakingModel/build/contracts/FirstClaimPool.json"; import UBIScheme from "@gooddollar/goodcontracts/stakingModel/build/contracts/UBIScheme.json"; import SchemeRegistrar from "@gooddollar/goodcontracts/build/contracts/SchemeRegistrar.json"; import AbsoluteVote from "@gooddollar/goodcontracts/build/contracts/AbsoluteVote.json"; import UpgradeScheme from "@gooddollar/goodcontracts/build/contracts/UpgradeScheme.json"; import GoodReserveCDai from "@gooddollar/goodcontracts/stakingModel/build/contracts/GoodReserveCDai.json"; import MarketMaker from "@gooddollar/goodcontracts/stakingModel/build/contracts/GoodMarketMaker.json"; import FundManager from "@gooddollar/goodcontracts/stakingModel/build/contracts/GoodFundManager.json"; import SimpleDAIStaking from "@gooddollar/goodcontracts/stakingModel/build/contracts/SimpleDAIStaking.json"; import BridgeMock from "@gooddollar/goodcontracts/stakingModel/build/contracts/BridgeMock.json"; import DonationsStaking from "@gooddollar/goodcontracts/upgradables/build/contracts/DonationsStaking.json"; import AdminWalletABI from "@gooddollar/goodcontracts/build/contracts/AdminWallet.json"; import OTPABI from "@gooddollar/goodcontracts/build/contracts/OneTimePayments.json"; import releaser from "../releaser"; import { increaseTime, deployUniswap } from "../../test/helpers"; import ProtocolSettings from "../../releases/deploy-settings.json"; const { name } = network; const printDeploy = (c: Contract): Contract => { console.log("deployed to: ", c.address); return c; }; export const deploy = async (networkName = name, single = false) => { console.log("dao deploying..."); //TODO: modify to deploy old DAO contracts version ie Reserve to truly simulate old DAO const dao = await createOldDAO(null, null, null); console.log("dao deployed"); const ubi = await deployUBI(dao); console.log("ubi deployed"); const gov = await deployOldVoting(dao); console.log("old vote deployed"); const adminWallet = await deployAdminWallet(dao); console.log("Admin wallet deployed"); const { uniswap, daiUsdOracle, compUsdOracle, usdcUsdOracle, aaveUsdOracle, daiethOracle, gasOracle, ethusdOracle, usdc, lendingPool, incentiveController } = await deploy3rdParty(dao); console.log(""); const release = { Reserve: dao.reserve.address, FundManager: dao.fundManager.address, GoodDollar: dao.gd, Identity: dao.identity, Avatar: dao.avatar, Controller: dao.controller, AbsoluteVote: gov.absoluteVote.address, SchemeRegistrar: gov.schemeRegistrar.address, UpgradeScheme: gov.upgradeScheme.address, DAI: dao.daiAddress, cDAI: dao.cdaiAddress, COMP: dao.COMP, USDC: usdc.address, Contribution: dao.contribution, DAIStaking: dao.simpleStaking, MarketMaker: dao.marketMaker.address, UBIScheme: ubi.ubiScheme.address, FirstClaimPool: ubi.firstClaim.address, HomeBridge: dao.bridge, ForeignBridge: dao.bridge, BancorFormula: dao.bancorFormula, DonationsStaking: dao.donationsStaking, UniswapRouter: uniswap.router.address, DAIUsdOracle: daiUsdOracle.address, COMPUsdOracle: compUsdOracle.address, USDCUsdOracle: usdcUsdOracle.address, AAVEUsdOracle: aaveUsdOracle.address, AaveLendingPool: lendingPool.address, GasPriceOracle: gasOracle.address, DAIEthOracle: daiethOracle.address, ETHUsdOracle: ethusdOracle.address, AaveIncentiveController: incentiveController.address, AdminWallet: adminWallet.address, OneTimePayments: dao.oneTimePayments, network: networkName, networkId: 4447 }; await releaser(release, networkName, "olddao"); if (single) await releaser(release, `${networkName}-mainnet`, "olddao"); return release; }; const deployAdminWallet = async dao => { const signers = await ethers.getSigners(); const adminWallet = await new ethers.ContractFactory( AdminWalletABI.abi, AdminWalletABI.bytecode, signers[0] ).deploy( signers.slice(0, 10).map(_ => _.address), ethers.utils.parseUnits("1000000", "gwei"), 4, dao.identity ); const id = await ethers.getContractAt("IIdentity", dao.identity); await id.addIdentityAdmin(adminWallet.address); await signers[0].sendTransaction({ to: adminWallet.address, value: ethers.utils.parseEther("10") }); return adminWallet; }; const deploy3rdParty = async dao => { //create et/dai pair let mintAmount = ethers.utils.parseEther("5000"); const ETHAmount = ethers.utils.parseEther("50"); const dai = await ethers.getContractAt("cERC20", dao.daiAddress); const comp = await ethers.getContractAt("DAIMock", dao.COMP); await dai["mint(uint256)"](mintAmount); const uniswap = await deployUniswap(comp, dai); await dai.approve(uniswap.router.address, mintAmount); const tokenUsdOracleFactory = await ethers.getContractFactory( "BatUSDMockOracle" ); const daiUsdOracle = await tokenUsdOracleFactory.deploy(); const usdcUsdOracle = await tokenUsdOracleFactory.deploy(); const compUsdOracle = await ( await ethers.getContractFactory("CompUSDMockOracle") ).deploy(); const aaveUsdOracle = await ( await ethers.getContractFactory("AaveUSDMockOracle") ).deploy(); const aave = await (await ethers.getContractFactory("AaveMock")).deploy(); const usdc = await (await ethers.getContractFactory("USDCMock")).deploy(); const lendingPool = await ( await ethers.getContractFactory("LendingPoolMock") ).deploy(usdc.address); const incentiveController = await ( await ethers.getContractFactory("IncentiveControllerMock") ).deploy(aave.address); const gasOracle = await ( await ethers.getContractFactory("GasPriceMockOracle") ).deploy(); const daiethOracle = await ( await ethers.getContractFactory("DaiEthPriceMockOracle") ).deploy(); const ethusdOracle = await ( await ethers.getContractFactory("EthUSDMockOracle") ).deploy(); return { uniswap, daiUsdOracle, compUsdOracle, aaveUsdOracle, usdcUsdOracle, gasOracle, daiethOracle, ethusdOracle, usdc, lendingPool, incentiveController }; }; export const deployKovanOldDAO = async () => { let { dai, cdai, comp } = ProtocolSettings[network.name].compound || {}; console.log("kovan dao deploying..."); const dao = await createOldDAO(dai, cdai, comp); console.log("dao deployed"); const gov = await deployOldVoting(dao); console.log("old vote deployed"); const release = { Reserve: dao.reserve.address, GoodDollar: dao.gd, Identity: dao.identity, Avatar: dao.avatar, Controller: dao.controller, AbsoluteVote: gov.absoluteVote.address, SchemeRegistrar: gov.schemeRegistrar.address, UpgradeScheme: gov.upgradeScheme.address, DAI: dao.daiAddress, cDAI: dao.cdaiAddress, COMP: dao.COMP, Contribution: dao.contribution, DAIStaking: dao.simpleStaking, MarketMaker: dao.marketMaker.address, Bridge: dao.bridge, BancorFormula: dao.bancorFormula, DonationsStaking: dao.donationsStaking, network: "kovan-mainnet", networkId: 42 }; releaser(release, network.name, "olddao"); }; export const createOldDAO = async (daiAddr, cdaiAddr, COMPAddr) => { let [root, ...signers] = await ethers.getSigners(); //generic call permissions let schemeMock = signers[signers.length - 1]; console.log("got signers:", { daiAddr, cdaiAddr, COMPAddr, root: root.address, schemeMock: schemeMock.address, balance: await ethers.provider .getBalance(root.address) .then(_ => _.toString()) }); const cdaiFactory = await ethers.getContractFactory("cDAIMock"); const daiFactory = await ethers.getContractFactory("DAIMock"); let dai = daiAddr ? await ethers.getContractAt("DAIMock", daiAddr) : await daiFactory.deploy(); let COMP = COMPAddr ? await ethers.getContractAt("DAIMock", COMPAddr) : await daiFactory.deploy(); let cDAI = cdaiAddr ? await ethers.getContractAt("DAIMock", cdaiAddr) : await cdaiFactory.deploy(dai.address); console.log("deployed erc20 tokens"); const DAOCreatorFactory = new ethers.ContractFactory( DAOCreatorABI.abi, DAOCreatorABI.bytecode, root ); const IdentityFactory = new ethers.ContractFactory( IdentityABI.abi, IdentityABI.bytecode, root ); const FeeFormulaFactory = new ethers.ContractFactory( FeeFormulaABI.abi, FeeFormulaABI.bytecode, root ); const AddFoundersFactory = new ethers.ContractFactory( AddFoundersABI.abi, AddFoundersABI.bytecode, root ); const BridgeFactory = new ethers.ContractFactory( BridgeMock.abi, BridgeMock.bytecode, root ); const BancorFormula = await ( await ethers.getContractFactory("BancorFormula") ).deploy(); // const BancorFormula = await ethers.getContractAt( // "BancorFormula", // "0x56ca74cd7b31609a8ba666308f089e0d5e2d0584" // ); const Bridge = await BridgeFactory.deploy().then(printDeploy); // const Bridge = await ethers.getContractAt( // BridgeMock.abi, // "0x8122241517e81b64F0fe56D6311981dF67965D87" // ); const AddFounders = await AddFoundersFactory.deploy().then(printDeploy); // const AddFounders = await ethers.getContractAt( // AddFoundersABI.abi, // "0x6F1BAbfF5E119d61F0c6d8653d84E8B284B87091" // ); const Identity = await IdentityFactory.deploy().then(printDeploy); // const Identity = await ethers.getContractAt( // IdentityABI.abi, // "0x77Bd4D825F4df162BDdda73a7E295c27e09E289f" // ); const daoCreator = await DAOCreatorFactory.deploy(AddFounders.address).then( printDeploy ); // const daoCreator = await ethers.getContractAt( // DAOCreatorABI.abi, // "0xfD1eFFDed0EE8739dF61B580F24bCd6585d0c6B4" // ); const FeeFormula = await FeeFormulaFactory.deploy(0).then(printDeploy); // const FeeFormula = await ethers.getContractAt( // FeeFormulaABI.abi, // "0x85b146AAa910aF4ab1D64cD81ab6f804aDf3053c" // ); await Identity.setAuthenticationPeriod(365); await daoCreator.forgeOrg( "G$", "G$", 0, FeeFormula.address, Identity.address, [root.address, signers[0].address, signers[1].address], 1000, [100000, 100000, 100000] ); const Avatar = new ethers.Contract( await daoCreator.avatar(), [ "function owner() view returns (address)", "function nativeToken() view returns (address)" ], root ); await Identity.setAvatar(Avatar.address); const controller = await Avatar.owner(); const ccFactory = new ethers.ContractFactory( ContributionCalculation.abi, ContributionCalculation.bytecode, root ); const contribution = await ccFactory .deploy(Avatar.address, 0, 1e15) .then(printDeploy); // const contribution = await ethers.getContractAt( // ContributionCalculation.abi, // "0xc3171409dB6827A68294B3A0D40a31310E83eD6B" // ); let goodReserveF = new ethers.ContractFactory( GoodReserveCDai.abi, GoodReserveCDai.bytecode, root ); console.log("deploying fundmanager..."); let fundManager = await new ethers.ContractFactory( FundManager.abi, FundManager.bytecode, root ) .deploy( Avatar.address, Identity.address, cDAI.address, ethers.constants.AddressZero, ethers.constants.AddressZero, 100 ) .then(printDeploy); // const fundManager = await ethers.getContractAt( // FundManager.abi, // "0x3D09770f01a3EdD0D910eC12d191Ac87C187aaD0" // ); console.log("deploying marketmaker..."); let marketMaker = await new ethers.ContractFactory( MarketMaker.abi, MarketMaker.bytecode, root ) .deploy(Avatar.address, 9999999999, 10000000000) .then(printDeploy); await marketMaker.initializeToken( cDAI.address, "100", //1gd "10000", //0.0001 cDai "1000000" //100% rr ); console.log("deploying reserve..."); let goodReserve = await goodReserveF .deploy( dai.address, cDAI.address, fundManager.address, Avatar.address, Identity.address, marketMaker.address, contribution.address, 100 ) .then(printDeploy); // const goodReserve = await ethers.getContractAt( // GoodReserveCDai.abi, // "0xA4F5687F95943F7D339829A165c9EA3962a8538b" // ); await marketMaker.transferOwnership(goodReserve.address); console.log("deploying simple staking"); const SimpleDAIStakingF = new ethers.ContractFactory( SimpleDAIStaking.abi, SimpleDAIStaking.bytecode, root ); const simpleStaking = await SimpleDAIStakingF.deploy( dai.address, cDAI.address, fundManager.address, 100, Avatar.address, Identity.address ).then(printDeploy); // const simpleStaking = await ethers.getContractAt( // SimpleDAIStaking.abi, // "0x6E20B9fadeA7432c0565aEbdA1aD28D7f082eAF2" // ); const DonationsStakingF = new ethers.ContractFactory( DonationsStaking.abi, DonationsStaking.bytecode, root ); console.log("deploy donationstaking"); const donationsStaking = await DonationsStakingF.deploy().then(printDeploy); // const donationsStaking = await ethers.getContractAt( // DonationsStaking.abi, // "0x912C6056BC5818E7Bc681e34dEfBBd2bC32080AB" // ); await donationsStaking.initialize( Avatar.address, simpleStaking.address, dai.address ); //fake donation staking for testing upgrade console.log("fake donations..."); await dai["mint(uint256)"](ethers.constants.WeiPerEther).catch(e => console.log("failed minting fake dai") ); await dai .transfer(donationsStaking.address, ethers.constants.WeiPerEther) .catch(e => console.log("failed fake dai transfer")); await donationsStaking .stakeDonations(0) .catch(e => console.log("failed staking fake dai")); await root .sendTransaction({ to: donationsStaking.address, value: ethers.constants.WeiPerEther.div(1000) }) .catch(e => console.log("failed transfering eth to donations")); console.log("done donations..."); console.log("Done deploying DAO, setting schemes permissions"); const ictrl = await ethers.getContractAt( "Controller", controller, schemeMock ); const setSchemes = async (addrs, params = []) => { for (let i in addrs) { await ictrl.registerScheme( addrs[i], params[i] || ethers.constants.HashZero, "0x0000001F", Avatar.address ); } }; const setReserveToken = async (token, gdReserve, tokenReserve, RR) => { const encoded = marketMaker.interface.encodeFunctionData( "initializeToken", [token, gdReserve, tokenReserve, RR] ); await ictrl.genericCall(marketMaker.address, encoded, Avatar.address, 0); }; const genericCall = (target, encodedFunc) => { return ictrl.genericCall(target, encodedFunc, Avatar.address, 0); }; const addWhitelisted = (addr, did, isContract = false) => { if (isContract) return Identity.addContract(addr); return Identity.addWhitelistedWithDID(addr, did); }; console.log("deploying OneTimePayments"); const otp = await new ethers.ContractFactory( OTPABI.abi, OTPABI.bytecode, root ) .deploy(Avatar.address, Identity.address) .then(printDeploy); console.log("setting schemes"); await daoCreator.setSchemes( Avatar.address, [ schemeMock.address, Identity.address, goodReserve.address, fundManager.address, simpleStaking.address, otp.address, FeeFormula.address ], [ ethers.constants.HashZero, ethers.constants.HashZero, ethers.constants.HashZero, ethers.constants.HashZero, ethers.constants.HashZero, ethers.constants.HashZero, ethers.constants.HashZero ], [ "0x0000001F", "0x0000001F", "0x0000001F", "0x0000001F", "0x0000001F", "0x0000001F", "0x0000001F" ], "" ); const gd = await Avatar.nativeToken(); //make GoodCap minter const encoded = ( await ethers.getContractAt("IGoodDollar", gd) ).interface.encodeFunctionData("addMinter", [goodReserve.address]); console.log("adding minter"); await ictrl.genericCall(gd, encoded, Avatar.address, 0); console.log("setting reserve token"); // await setReserveToken( // cDAI.address, // "100", //1gd // "10000", //0.0001 cDai // "1000000" //100% rr // ); console.log("starting..."); await goodReserve.start(); await fundManager.start(); await simpleStaking.start(); return { fundManager, daoCreator, controller, reserve: goodReserve, avatar: await daoCreator.avatar(), gd: await Avatar.nativeToken(), identity: Identity.address, setSchemes, setReserveToken, genericCall, addWhitelisted, marketMaker, feeFormula: FeeFormula, daiAddress: dai.address, cdaiAddress: cDAI.address, COMP: COMP.address, contribution: contribution.address, simpleStaking: simpleStaking.address, bancorFormula: BancorFormula.address, bridge: Bridge.address, donationsStaking: donationsStaking.address, oneTimePayments: otp.address }; }; export const deployUBI = async deployedDAO => { let { nameService, setSchemes, genericCall, avatar, identity, gd } = deployedDAO; const fcFactory = new ethers.ContractFactory( FirstClaimPool.abi, FirstClaimPool.bytecode, (await ethers.getSigners())[0] ); console.log("deploying first claim...", { avatar, identity }); const firstClaim = await fcFactory.deploy(avatar, identity, 1000); console.log("deploying ubischeme and starting..."); const now = await ethers.provider.getBlock("latest"); let ubiScheme = await new ethers.ContractFactory( UBIScheme.abi, UBIScheme.bytecode, ( await ethers.getSigners() )[0] ).deploy( avatar, identity, firstClaim.address, now.timestamp, now.timestamp + 10000, 14, 7 ); let encoded = ( await ethers.getContractAt("IGoodDollar", gd) ).interface.encodeFunctionData("mint", [firstClaim.address, 1000000]); await genericCall(gd, encoded); encoded = ( await ethers.getContractAt("IGoodDollar", gd) ).interface.encodeFunctionData("mint", [ubiScheme.address, 1000000]); await genericCall(gd, encoded); console.log("set firstclaim,ubischeme as scheme and starting..."); await setSchemes([firstClaim.address, ubiScheme.address]); const lastBlock = await ethers.provider.getBlock("latest"); const periodStart = await ubiScheme.periodStart().then(_ => _.toNumber()); const diff = periodStart - lastBlock.timestamp; console.log("ubischeme start:", { now: now.timestamp, blockTime: lastBlock.timestamp, periodStart: await ubiScheme.periodStart().then(_ => _.toString()), periodEnd: await ubiScheme.periodEnd().then(_ => _.toString()), diff }); if (diff > 0 && diff < 2 ** 64) await increaseTime(diff); //make sure period start has reached const tx = await firstClaim.start(); console.log("firstclaim started"); await ubiScheme.start(); console.log("ubischeme started"); await increaseTime(10000); //make sure period end of ubischeme has reached return { firstClaim, ubiScheme }; }; export const deployOldVoting = async dao => { try { const SchemeRegistrarF = new ethers.ContractFactory( SchemeRegistrar.abi, SchemeRegistrar.bytecode, (await ethers.getSigners())[0] ); const UpgradeSchemeF = new ethers.ContractFactory( UpgradeScheme.abi, UpgradeScheme.bytecode, (await ethers.getSigners())[0] ); const AbsoluteVoteF = new ethers.ContractFactory( AbsoluteVote.abi, AbsoluteVote.bytecode, (await ethers.getSigners())[0] ); console.log("dpeloying voting schemes"); const absoluteVote = await AbsoluteVoteF.deploy().then(printDeploy); const upgradeScheme = await UpgradeSchemeF.deploy().then(printDeploy); const schemeRegistrar = await SchemeRegistrarF.deploy().then(printDeploy); // const [absoluteVote, upgradeScheme, schemeRegistrar] = await Promise.all([ // AbsoluteVoteF.deploy(), // UpgradeSchemeF.deploy(), // SchemeRegistrarF.deploy() // ]); console.log("setting parameters"); const voteParametersHash = await absoluteVote.getParametersHash( 50, ethers.constants.AddressZero ); console.log("setting params for voting machine and schemes"); await schemeRegistrar.setParameters( voteParametersHash, voteParametersHash, absoluteVote.address ); await absoluteVote.setParameters(50, ethers.constants.AddressZero); await upgradeScheme.setParameters(voteParametersHash, absoluteVote.address); const upgradeParametersHash = await upgradeScheme.getParametersHash( voteParametersHash, absoluteVote.address ); // Deploy SchemeRegistrar const schemeRegisterParams = await schemeRegistrar.getParametersHash( voteParametersHash, voteParametersHash, absoluteVote.address ); let schemesArray; let paramsArray; // Subscribe schemes console.log("setting voting schemes"); schemesArray = [schemeRegistrar.address, upgradeScheme.address]; paramsArray = [schemeRegisterParams, upgradeParametersHash]; await dao.setSchemes(schemesArray, paramsArray); return { schemeRegistrar, upgradeScheme, absoluteVote }; } catch (e) { console.log("deployVote failed", e); } }; if (process.env.TEST != "true" && name.startsWith("develop")) { console.log("deploying non-test localOldDao"); if (network.name.includes("kovan")) { deployKovanOldDAO().catch(console.log); } else deploy(name).catch(console.log); }