@gooddollar/goodprotocol
Version:
GoodDollar Protocol
191 lines (165 loc) • 6.76 kB
text/typescript
/***
* complete deploy of the new G$ savings concept
* steps required:
* sidechain
* 1. deploy GoodDollarMintBurnWrapper
* 2. deploy G$Savings
* 3. create proposal to:
* - add G$Savings as rewards minter on GoodDollarMintBurnWraper
* - register GoodDollarMintBurnWrapper as scheme so it can call mint on controller
* - register G$Savings as scheme so it can handle upgrade from GovernanceStaking
* - add GoodDollarMintBurnWraper to name service
*
* mainnet:
* 1. deploy new reserve implementation
* 2. deploy DistributionHelper
* 3. create proposal to upgrade reserve
*
*/
import { network, ethers, upgrades, run } from "hardhat";
import { Contract, Signer } from "ethers";
import { defaultsDeep } from "lodash";
import {
deployDeterministic,
printDeploy,
executeViaGuardian,
executeViaSafe,
verifyProductionSigner
} from "./helpers";
import releaser from "../../scripts/releaser";
import ProtocolSettings from "../../releases/deploy-settings.json";
import dao from "../../releases/deployment.json";
import { deployWrapper } from "./multichainWrapper-deploy";
import { GoodDollarMintBurnWrapper, Controller, NameService } from "../../types";
const { name: networkName } = network;
export const deploySidechain = async () => {
const isProduction = networkName.includes("production");
let [root] = await ethers.getSigners();
if (isProduction) verifyProductionSigner(root);
let release: { [key: string]: any } = dao[networkName];
let settings = defaultsDeep({}, ProtocolSettings[networkName], ProtocolSettings["default"]);
console.log("got signers:", {
networkName,
root: root.address,
balance: await ethers.provider.getBalance(root.address).then(_ => _.toString())
});
let Wrapper;
if (!release.GoodDollarMintBurnWrapper) Wrapper = (await deployWrapper(release.Avatar)) as GoodDollarMintBurnWrapper;
else {
Wrapper = await ethers.getContractAt("GoodDollarMintBurnWrapper", release.GoodDollarMintBurnWrapper);
}
console.log("deploying savings...");
let GDSavings;
if (!release.GoodDollarStaking) {
GDSavings = (await deployDeterministic(
{
name: "GoodDollarStaking",
isUpgradeable: false
},
[
release.NameService,
ethers.BigNumber.from(settings.savings.blockAPY),
ethers.BigNumber.from(settings.savings.blocksPerYear),
settings.savings.daysUntilUpgrade
]
).then(printDeploy)) as Contract;
let torelease = {
GoodDollarStaking: GDSavings.address
};
await releaser(torelease, networkName, "deployment", false);
} else {
GDSavings = await ethers.getContractAt("GoodDollarStaking", release.GoodDollarStaking);
}
if (networkName.includes("production"))
return console.log("Skipping proposal/upgrade for production, need to perform manually");
await executeProposal(GDSavings.address, Wrapper.address, settings.guardiansSafe);
};
const executeProposal = async (savingsAddress: string, wrapperAddress: string, guardiansSafe: string) => {
console.log("executing savings + wrapper proposal");
const isProduction = networkName.includes("production");
const viaGuardians = false;
let release: { [key: string]: any } = dao[networkName];
savingsAddress = savingsAddress || release.GoodDollarStaking;
wrapperAddress = wrapperAddress || release.GoodDollarMintBurnWrapper;
let [root] = await ethers.getSigners();
/// we now use guardians and not direct onchain voting, so no need for proposer
//on celo we dont need voting yet to deploy it.
//dev env dont use voting for test purposes
// const proposer =
// !networkName.includes("celo") &&
// (isProduction || networkName.includes("staging"))
// ? new ethers.Wallet(process.env.PROPOSER_KEY, ethers.provider)
// : root; //need proposer with 0.3% of GOOD tokens
const ctrl = (await ethers.getContractAt("Controller", release.Controller)) as Controller;
const ns = (await ethers.getContractAt("NameService", release.NameService)) as NameService;
const proposalContracts = [
wrapperAddress, //MinterWrapper -> add GDSavings
ctrl.address, //controller -> add MinterWrapper as scheme
ctrl.address, // controller -> add GDSavings as scheme
ns.address //nameservice add MinterWrapper
];
const proposalEthValues = proposalContracts.map(_ => 0);
const proposalFunctionSignatures = [
"addMinter(address,uint256,uint256,uint32,uint256,uint256,uint32,bool)", //add gooddollarstaking as minter in gooddollarwrapper
"registerScheme(address,bytes32,bytes4,address)", //make sure gooddollarwrapper is a registered scheme so it can mint G$ tokens
"registerScheme(address,bytes32,bytes4,address)", //make sure gdsavings has generic call so it can perform the upgrade process
"setAddress(string,address)" //add gooddollarwrapper in nameservice
];
const proposalFunctionInputs = [
ethers.utils.defaultAbiCoder.encode(
["address", "uint256", "uint256", "uint32", "uint256", "uint256", "uint32", "bool"],
[savingsAddress, 0, 0, 30, 0, 0, 0, true]
), //function addMinter(
ethers.utils.defaultAbiCoder.encode(
["address", "bytes32", "bytes4", "address"],
[
wrapperAddress, //scheme
ethers.constants.HashZero, //paramshash
"0x00000001", //permissions - minimal
release.Avatar
]
),
ethers.utils.defaultAbiCoder.encode(
["address", "bytes32", "bytes4", "address"],
[
savingsAddress, //scheme
ethers.constants.HashZero, //paramshash
"0x000000f1", //permissions - genericcall
release.Avatar
]
),
ethers.utils.defaultAbiCoder.encode(["string", "address"], ["MINTBURN_WRAPPER", wrapperAddress])
];
if (!viaGuardians) {
console.log("upgrading via owner...");
await executeViaGuardian(
proposalContracts,
proposalEthValues,
proposalFunctionSignatures,
proposalFunctionInputs,
root
);
} else {
console.log("upgrading via guardians safe...");
//create proposal
await executeViaSafe(
proposalContracts,
proposalEthValues,
proposalFunctionSignatures,
proposalFunctionInputs,
guardiansSafe
);
}
const Controller = await ethers.getContractAt("Controller", release.Controller);
const wrapperDaoPermissions = await Controller.getSchemePermissions(wrapperAddress, release.Avatar);
const savingsDaoPermissions = await Controller.getSchemePermissions(savingsAddress, release.Avatar);
console.log({
wrapperDaoPermissions,
savingsDaoPermissions
});
};
export const main = async () => {
await deploySidechain();
// await executeProposal(undefined, undefined);
};
if (process.argv[1].includes("gdSavings")) main();