@gooddollar/goodprotocol
Version:
GoodDollar Protocol
248 lines (206 loc) • 8.65 kB
text/typescript
/***
* to get same addresses as on Celo
* deploy proxyfactory with 0x271cd5391016eb621aB3f9c0c70F5cF91DFd3FB0 with nonce 2
* create a gnosissafe with 0x3de7216149f12d8f51540d9a870149560fc11bfb with nonce 3
* run this script with 0x3de7216149f12d8f51540d9a870149560fc11bfb with nonce 7
*/
import { network, ethers, upgrades, run } from "hardhat";
import { Contract } from "ethers";
import { defaultsDeep } from "lodash";
// import DAOCreatorABI from "@gooddollar/goodcontracts/build/contracts/DaoCreatorGoodDollar.json";
import DAOCreatorABI from "@gooddollar/goodcontracts/build/contracts/DaoCreatorGoodDollarWithTokens.json";
// import IdentityABI from "@gooddollar/goodcontracts/build/contracts/Identity.json";
import FeeFormulaABI from "@gooddollar/goodcontracts/build/contracts/FeeFormula.json";
import { deployDeterministic, deploySuperGoodDollar, verifyProductionSigner } from "./helpers";
import releaser from "../releaser";
import ProtocolSettings from "../../releases/deploy-settings.json";
import dao from "../../releases/deployment.json";
import { TransactionResponse } from "@ethersproject/providers";
const printDeploy = async (c: Contract | TransactionResponse): Promise<Contract | TransactionResponse> => {
if (c instanceof Contract) {
await c.deployed();
console.log("deployed to: ", c.address);
}
if (c.wait) {
await c.wait();
console.log("tx done:", c.hash);
}
return c;
};
export const createDAO = async () => {
let protocolSettings = defaultsDeep({}, ProtocolSettings[network.name], ProtocolSettings["default"]);
let release: { [key: string]: any } = dao[network.name];
const isProduction = network.name.includes("production");
let [root] = await ethers.getSigners();
const daoOwner = root.address;
if (isProduction) verifyProductionSigner(root);
console.log("got signers:", {
network,
daoOwner,
root: root.address,
balance: await ethers.provider.getBalance(root.address).then(_ => _.toString()),
release
});
const DAOCreatorFactory = new ethers.ContractFactory(DAOCreatorABI.abi, DAOCreatorABI.bytecode, root);
const FeeFormulaFactory = new ethers.ContractFactory(FeeFormulaABI.abi, FeeFormulaABI.bytecode, root);
const proxyFactory = await ethers.getContractAt("ProxyFactory1967", release.ProxyFactory);
const salt = ethers.BigNumber.from(ethers.utils.keccak256(ethers.utils.toUtf8Bytes("NameService")));
const nameserviceFutureAddress = await proxyFactory["getDeploymentAddress(uint256,address)"](salt, root.address);
console.log("deploying identity", { nameserviceFutureAddress });
let Identity;
if (release.Identity) Identity = await ethers.getContractAt("IdentityV2", release.Identity);
else
Identity = (await deployDeterministic(
{
name: "IdentityV2",
salt: "Identity",
isUpgradeable: true
},
[root.address, ethers.constants.AddressZero]
).then(printDeploy)) as Contract;
let daoCreator;
if (release.DAOCreator) daoCreator = await DAOCreatorFactory.attach(release.DAOCreator);
else daoCreator = (await DAOCreatorFactory.deploy().then(printDeploy)) as Contract;
let FeeFormula;
if (release.FeeFormula) FeeFormula = await FeeFormulaFactory.attach(release.FeeFormula);
else
FeeFormula = (await deployDeterministic({ name: "FeeFormula", factory: FeeFormulaFactory }, [0]).then(
printDeploy
)) as Contract;
let GoodDollar;
let { superfluidHost, superfluidInflowNFTLogic, superfluidOutflowNFTLogic } =
protocolSettings;
if (protocolSettings.superfluidHost) {
GoodDollar = await deploySuperGoodDollar(
{
superfluidHost,
superfluidInflowNFTLogic,
superfluidOutflowNFTLogic
},
[
isProduction ? "GoodDollar" : "GoodDollar Dev",
"G$",
0,
FeeFormula.address,
Identity.address,
ethers.constants.AddressZero,
daoCreator.address
]
);
} else {
GoodDollar = (await deployDeterministic(
{
name: "GoodDollar",
isUpgradeable: true,
initializer: "initialize(string, string, uint256, address, address, address,address)"
},
[
isProduction ? "GoodDollar" : "GoodDollar Dev",
"G$",
0,
FeeFormula.address,
Identity.address,
ethers.constants.AddressZero,
daoCreator.address
]
).then(printDeploy)) as Contract;
}
const GReputation = (await deployDeterministic(
{
name: "GReputation",
isUpgradeable: true,
initializer: "initialize(address, string, bytes32, uint256)"
},
[
ethers.constants.AddressZero,
"fuse",
protocolSettings.governance.gdaoAirdrop, //should fail on real deploy if not set
protocolSettings.governance.gdaoTotalSupply //should fail on real deploy if not set
]
).then(printDeploy)) as Contract;
// console.log("setting identity auth period");
// await Identity.setAuthenticationPeriod(365).then(printDeploy);
console.log("creating dao");
await daoCreator.forgeOrg(GoodDollar.address, GReputation.address, [], 0, []).then(printDeploy);
console.log("forgeOrg done ");
const Avatar = new ethers.Contract(
await daoCreator.avatar(),
["function owner() view returns (address)", "function nativeToken() view returns (address)"],
root
);
console.log("Done deploying DAO, setting schemes permissions");
let schemes = [daoOwner, Identity.address];
const gd = await Avatar.nativeToken();
const controller = await Avatar.owner();
console.log("setting schemes", schemes);
await daoCreator
.setSchemes(
Avatar.address,
schemes,
schemes.map(_ => ethers.constants.HashZero),
["0x0000001f", "0x00000001"],
""
)
.then(printDeploy);
const NameService = await deployDeterministic({ name: "NameService", isUpgradeable: true }, [
controller,
["CONTROLLER", "AVATAR", "IDENTITY", "GOODDOLLAR", "REPUTATION"].map(_ =>
ethers.utils.keccak256(ethers.utils.toUtf8Bytes(_))
),
[controller, Avatar.address, Identity.address, gd, GReputation.address]
]);
console.log("set GRep nameservice..");
await (await GReputation.updateDAO(NameService.address)).wait();
console.log("set Identity nameservice..");
await Identity.initDAO(NameService.address).then(printDeploy);
//verifications
const Controller = await ethers.getContractAt("Controller", controller);
if (isProduction) {
console.log("renouncing minting rights on production env");
await GoodDollar.renounceMinter().then(printDeploy);
}
const daoOwnerDaoPermissions = await Controller.getSchemePermissions(daoOwner, Avatar.address);
const deployerIsNotGDMinter = (await GoodDollar.isMinter(root.address)) === false;
const avatarIsGDMinter = await GoodDollar.isMinter(Avatar.address);
const deployerIsNotGDPauser = (await GoodDollar.isPauser(root.address)) === false;
const deployerIsNotRepMinter = (await GReputation.hasRole(GReputation.MINTER_ROLE(), root.address)) === false;
const avatarIsRepMinter = await GReputation.hasRole(GReputation.MINTER_ROLE(), Avatar.address);
const deployerIsIdentityOwner = await Identity.hasRole(ethers.constants.HashZero, root.address);
const avatarIsIdentityOwner = await Identity.hasRole(ethers.constants.HashZero, Avatar.address);
//try to modify DAO -> should not succeed
await (await GReputation.updateDAO(ethers.constants.AddressZero)).wait();
const grepHasDAOSet = (await GReputation.nameService()) === NameService.address;
const factoryIsNotGoodOwner = (await GReputation.hasRole(ethers.constants.HashZero, proxyFactory.address)) === false;
const factoryIsNotGDMinter = (await GoodDollar.isMinter(proxyFactory.address)) === false;
const factoryIsNotGDPauser = (await GoodDollar.isPauser(root.address)) === false;
console.log({
daoOwnerDaoPermissions,
deployerIsNotGDMinter,
deployerIsNotRepMinter,
deployerIsNotGDPauser,
factoryIsNotGoodOwner,
factoryIsNotGDMinter,
factoryIsNotGDPauser,
avatarIsRepMinter,
deployerIsIdentityOwner,
avatarIsIdentityOwner,
avatarIsGDMinter,
grepHasDAOSet
});
release = {
// ProxyFactory: "0x99C22e78A579e2176311c736C4c9F0b0D5A47806",
GoodDollar: gd,
Avatar: Avatar.address,
Controller: controller,
Identity: Identity.address,
NameService: NameService.address,
GReputation: GReputation.address,
FeeFormula: FeeFormula.address,
DAOCreator: daoCreator.address
};
await releaser(release, network.name, "deployment", false);
};
export const main = async () => {
await createDAO();
};
main();