|
| 1 | +import { interfaceName } from "../../Constants"; |
| 2 | +import { task } from "hardhat/config"; |
| 3 | +import { Contract } from "web3-eth-contract"; |
| 4 | +import { CombinedHRE } from "./types"; |
| 5 | +import { GovernorV2RolesEnum, TokenRolesEnum } from "../../Enums"; |
| 6 | +import Web3 from "web3"; |
| 7 | +const { padRight, utf8ToHex } = Web3.utils; |
| 8 | + |
| 9 | +type InterfaceName = keyof typeof interfaceName; |
| 10 | +function isInterfaceName(name: string): name is InterfaceName { |
| 11 | + return name in interfaceName; |
| 12 | +} |
| 13 | + |
| 14 | +const registeredContracts = new Set([ |
| 15 | + "OptimisticOracle", |
| 16 | + "OptimisticOracleV2", |
| 17 | + "OptimisticOracleV3", |
| 18 | + "SkinnyOptimisticOracle", |
| 19 | + "SkinnyOptimisticOracleV2", |
| 20 | + "GovernorV2", |
| 21 | + "ProposerV2", |
| 22 | +]); |
| 23 | + |
| 24 | +// Gets all contract deployments that can be added to the Finder. |
| 25 | +async function getContractsForFinder(hre_: CombinedHRE, mockOracle: boolean) { |
| 26 | + const { deployments, web3 } = hre_; |
| 27 | + |
| 28 | + const supportedFinderContracts = Object.keys(interfaceName); |
| 29 | + const contractsForFinder = new Map<InterfaceName, Contract>(); |
| 30 | + |
| 31 | + for (const contractName of supportedFinderContracts) { |
| 32 | + if (!isInterfaceName(contractName)) throw new Error(`No mapped interface name for contract name ${contractName}`); |
| 33 | + |
| 34 | + // Depending on mockOracle flag skip either VotingV2 or MockOracleAncillary |
| 35 | + if (mockOracle && contractName === "VotingV2") continue; |
| 36 | + if (!mockOracle && contractName === "MockOracleAncillary") continue; |
| 37 | + |
| 38 | + try { |
| 39 | + const deployed = await deployments.get(contractName); |
| 40 | + contractsForFinder.set(contractName, new web3.eth.Contract(deployed.abi, deployed.address)); |
| 41 | + } catch { |
| 42 | + // Do nothing if network does not have this contract deployed. |
| 43 | + } |
| 44 | + } |
| 45 | + |
| 46 | + return contractsForFinder; |
| 47 | +} |
| 48 | + |
| 49 | +// Gets all contract deployments that can be added to the Registry. |
| 50 | +async function getContractsForRegistry(hre_: CombinedHRE) { |
| 51 | + const { deployments } = hre_; |
| 52 | + |
| 53 | + const contractsForRegistry = new Map<string, string>(); |
| 54 | + |
| 55 | + for (const contractName of registeredContracts) { |
| 56 | + try { |
| 57 | + const deployed = await deployments.get(contractName); |
| 58 | + contractsForRegistry.set(contractName, deployed.address); |
| 59 | + } catch { |
| 60 | + // Do nothing if network does not have this contract deployed. |
| 61 | + } |
| 62 | + } |
| 63 | + |
| 64 | + return contractsForRegistry; |
| 65 | +} |
| 66 | + |
| 67 | +task("setup-dvmv2-testnet", "Configures DVMv2 on L1 testnet") |
| 68 | + .addFlag("mockoracle", "Use if you want to set MockOracleAncillary as the Oracle") |
| 69 | + .setAction(async function (taskArguments, hre_) { |
| 70 | + const hre = hre_ as CombinedHRE; |
| 71 | + const { deployments, getNamedAccounts, web3 } = hre; |
| 72 | + const { deployer } = await getNamedAccounts(); |
| 73 | + const { mockoracle } = taskArguments; |
| 74 | + |
| 75 | + /** *********************************** |
| 76 | + * Adding contracts to Finder |
| 77 | + *************************************/ |
| 78 | + |
| 79 | + const Finder = await deployments.get("Finder"); |
| 80 | + const finder = new web3.eth.Contract(Finder.abi, Finder.address); |
| 81 | + console.log(`Using Finder @ ${finder.options.address}`); |
| 82 | + |
| 83 | + const contractsForFinder = await getContractsForFinder(hre, !!mockoracle); |
| 84 | + for (const [contractName, contract] of contractsForFinder) { |
| 85 | + const nameInFinder = interfaceName[contractName]; |
| 86 | + |
| 87 | + const identifierHex = padRight(utf8ToHex(nameInFinder), 64); |
| 88 | + const currentlySetAddress = await finder.methods.interfacesImplemented(identifierHex).call(); |
| 89 | + if (currentlySetAddress !== contract.options.address) { |
| 90 | + const txn = await finder.methods |
| 91 | + .changeImplementationAddress(identifierHex, contract.options.address) |
| 92 | + .send({ from: deployer }); |
| 93 | + console.log( |
| 94 | + `Set ${contractName} in Finder to "${nameInFinder}" @ ${contract.options.address}, tx: ${txn.transactionHash}` |
| 95 | + ); |
| 96 | + } else { |
| 97 | + console.log(`Already set ${contractName} in Finder to "${nameInFinder}" @ ${contract.options.address}`); |
| 98 | + } |
| 99 | + } |
| 100 | + |
| 101 | + /** *********************************** |
| 102 | + * Adding contracts to Registry |
| 103 | + *************************************/ |
| 104 | + |
| 105 | + const contractsForRegistry = await getContractsForRegistry(hre); |
| 106 | + for (const [contractName, account] of contractsForRegistry) { |
| 107 | + console.log(`Trying to add ${contractName} to Registry`); |
| 108 | + await hre.run("register-accounts", { account }); |
| 109 | + } |
| 110 | + |
| 111 | + /** *********************************** |
| 112 | + * Adding minter role for VotingV2 |
| 113 | + *************************************/ |
| 114 | + |
| 115 | + const VotingToken = await deployments.get("VotingToken"); |
| 116 | + const votingToken = new web3.eth.Contract(VotingToken.abi, VotingToken.address); |
| 117 | + console.log(`Using VotingToken @ ${votingToken.options.address}`); |
| 118 | + |
| 119 | + const VotingV2 = await deployments.get("VotingV2"); |
| 120 | + |
| 121 | + const hasMinterRole = await votingToken.methods.holdsRole(TokenRolesEnum.MINTER, VotingV2.address).call(); |
| 122 | + if (!hasMinterRole) { |
| 123 | + const txn = await votingToken.methods.addMember(TokenRolesEnum.MINTER, VotingV2.address).send({ from: deployer }); |
| 124 | + console.log(`Added token minter role to VotingV2 @ ${VotingV2.address}, tx: ${txn.transactionHash}`); |
| 125 | + } else { |
| 126 | + console.log(`VotingV2 @ ${VotingV2.address} already has token minter role`); |
| 127 | + } |
| 128 | + |
| 129 | + /** *********************************** |
| 130 | + * Setting up roles for GovernorV2 |
| 131 | + *************************************/ |
| 132 | + |
| 133 | + const GovernorV2 = await deployments.get("GovernorV2"); |
| 134 | + const governorV2 = new web3.eth.Contract(GovernorV2.abi, GovernorV2.address); |
| 135 | + console.log(`Using GovernorV2 @ ${governorV2.options.address}`); |
| 136 | + |
| 137 | + const ProposerV2 = await deployments.get("ProposerV2"); |
| 138 | + const hasProposerRole = await governorV2.methods.holdsRole(GovernorV2RolesEnum.PROPOSER, ProposerV2.address).call(); |
| 139 | + if (!hasProposerRole) { |
| 140 | + const txn = await governorV2.methods |
| 141 | + .resetMember(GovernorV2RolesEnum.PROPOSER, ProposerV2.address) |
| 142 | + .send({ from: deployer }); |
| 143 | + console.log(`Reset proposer role to ProposerV2 @ ${ProposerV2.address}, tx: ${txn.transactionHash}`); |
| 144 | + } else { |
| 145 | + console.log(`ProposerV2 @ ${ProposerV2.address} already has proposer role`); |
| 146 | + } |
| 147 | + |
| 148 | + const EmergencyProposer = await deployments.get("EmergencyProposer"); |
| 149 | + const hasEmergencyProposerRole = await governorV2.methods |
| 150 | + .holdsRole(GovernorV2RolesEnum.EMERGENCY_PROPOSER, EmergencyProposer.address) |
| 151 | + .call(); |
| 152 | + if (!hasEmergencyProposerRole) { |
| 153 | + const txn = await governorV2.methods |
| 154 | + .resetMember(GovernorV2RolesEnum.EMERGENCY_PROPOSER, EmergencyProposer.address) |
| 155 | + .send({ from: deployer }); |
| 156 | + console.log( |
| 157 | + `Reset emergency proposer role to EmergencyProposer @ ${EmergencyProposer.address}, tx: ${txn.transactionHash}` |
| 158 | + ); |
| 159 | + } else { |
| 160 | + console.log(`EmergencyProposer @ ${EmergencyProposer.address} already has emergency proposer role`); |
| 161 | + } |
| 162 | + |
| 163 | + /** *********************************** |
| 164 | + * Sync OptimisticOracleV3 |
| 165 | + *************************************/ |
| 166 | + |
| 167 | + // If Oracle was changed OptimisticOracleV3 requires syncing its cached values. We do this only if already have |
| 168 | + // deployed OptimisticOracleV3 for the network. |
| 169 | + try { |
| 170 | + const OptimisticOracleV3 = await deployments.get("OptimisticOracleV3"); |
| 171 | + const optimisticOraclev3 = new web3.eth.Contract(OptimisticOracleV3.abi, OptimisticOracleV3.address); |
| 172 | + console.log(`Using OptimisticOracleV3 @ ${optimisticOraclev3.options.address}`); |
| 173 | + |
| 174 | + const defaultIdentifier = await optimisticOraclev3.methods.defaultIdentifier().call(); |
| 175 | + const defaultCurrency = await optimisticOraclev3.methods.defaultCurrency().call(); |
| 176 | + const txn = await optimisticOraclev3.methods |
| 177 | + .syncUmaParams(defaultIdentifier, defaultCurrency) |
| 178 | + .send({ from: deployer }); |
| 179 | + console.log(`Synced OptimisticOracleV3 cached params, tx: ${txn.transactionHash}`); |
| 180 | + } catch { |
| 181 | + console.log("OptimisticOracleV3 not deployed for this network"); |
| 182 | + } |
| 183 | + }); |
0 commit comments