UNPKG

@dydxfoundation/governance

Version:
98 lines (97 loc) 5.51 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.executeSafetyModuleUpgradeNoProposal = exports.executeSafetyModuleUpgradeViaProposal = void 0; const bignumber_js_1 = __importDefault(require("bignumber.js")); const utils_1 = require("ethers/lib/utils"); const config_1 = __importDefault(require("../../src/config")); const deploy_config_1 = require("../../src/deploy-config"); const get_deployer_address_1 = require("../../src/deploy-config/get-deployer-address"); const logging_1 = require("../../src/lib/logging"); const util_1 = require("../../src/lib/util"); const impersonate_account_1 = require("../../src/migrations/helpers/impersonate-account"); const safety_module_fix_proposal_1 = require("../../src/migrations/safety-module-fix-proposal"); const types_1 = require("../../types"); const evm_1 = require("../helpers/evm"); const MOCK_PROPOSAL_IPFS_HASH = ('0x0000000000000000000000000000000000000000000000000000000000000000'); async function executeSafetyModuleUpgradeViaProposal({ dydxTokenAddress, governorAddress, longTimelockAddress, safetyModuleAddress, safetyModuleProxyAdminAddress, safetyModuleNewImplAddress, }) { const deployConfig = (0, deploy_config_1.getDeployConfig)(); const deployer = await (0, get_deployer_address_1.getDeployerSigner)(); const dydxToken = new types_1.DydxToken__factory(deployer).attach(dydxTokenAddress); const governor = new types_1.DydxGovernor__factory(deployer).attach(governorAddress); // Pick a voter with enough tokens to meet the quorum requirement. const voterAddress = deployConfig.TOKEN_ALLOCATIONS.DYDX_TRADING.ADDRESS; const voter = await (0, impersonate_account_1.impersonateAndFundAccount)(voterAddress); const voterBalance = await dydxToken.balanceOf(voterAddress); if (voterBalance.lt(new bignumber_js_1.default('1e26').toFixed())) { throw new Error('Not enough votes to pass the proposal.'); } // Vote on an existing proposal (can be used with mainnet forking). let proposalId; if (config_1.default.SM_FIX_PROPOSAL_ID !== null) { proposalId = config_1.default.SM_FIX_PROPOSAL_ID; } else { (0, logging_1.log)('Creating proposal'); ({ proposalId } = await (0, safety_module_fix_proposal_1.createSafetyModuleFixProposal)({ proposalIpfsHashHex: MOCK_PROPOSAL_IPFS_HASH, governorAddress, longTimelockAddress, safetyModuleAddress, safetyModuleProxyAdminAddress, safetyModuleNewImplAddress, signer: voter, })); (0, logging_1.log)('Waiting for voting to begin'); for (let i = 0; i < deployConfig.VOTING_DELAY_BLOCKS + 1; i++) { if (i > 0 && i % 2000 === 0) { (0, logging_1.log)('mining', i); } await (0, evm_1.advanceBlock)(); } } let proposalState = await governor.getProposalState(proposalId); if (proposalState !== 2) { throw new Error('Expected proposal to be in the voting phase.'); } (0, logging_1.log)('Submitting vote'); await (0, util_1.waitForTx)(await governor.connect(voter).submitVote(proposalId, true)); (0, logging_1.log)('Waiting for voting to end'); let minedCount = 0; for (;;) { for (let i = 0; i < 2000; i++) { await (0, evm_1.advanceBlock)(); minedCount++; } (0, logging_1.log)('mining', minedCount); proposalState = await governor.getProposalState(proposalId); if (proposalState !== 2) { break; } } if (proposalState !== 4) { throw new Error(`Expected proposal to have succeeded but state was ${proposalState}`); } (0, logging_1.log)('Queueing the proposal'); await (0, util_1.waitForTx)(await governor.queue(proposalId)); const delaySeconds = deployConfig.LONG_TIMELOCK_CONFIG.DELAY; await (0, evm_1.increaseTimeAndMine)(delaySeconds); (0, logging_1.log)('Executing the proposal'); await (0, util_1.waitForTx)(await governor.execute(proposalId)); (0, logging_1.log)('Proposal executed'); (0, logging_1.log)('\n=== SAFETY MODULE FIX COMPLETE ===\n'); } exports.executeSafetyModuleUpgradeViaProposal = executeSafetyModuleUpgradeViaProposal; async function executeSafetyModuleUpgradeNoProposal({ longTimelockAddress, safetyModuleAddress, safetyModuleProxyAdminAddress, safetyModuleNewImplAddress, }) { // NOTE: On mainnet, the upgrade and the call to the initializer are performed atomically // via a governance proposal. It's important that these steps are atomic or else the // initializer can be called to extract funds from the contract. const mockLongTimelock = await (0, impersonate_account_1.impersonateAndFundAccount)(longTimelockAddress); const safetyModuleProxyAdmin = new types_1.ProxyAdmin__factory(mockLongTimelock).attach(safetyModuleProxyAdminAddress); const initializeCalldata = new utils_1.Interface(types_1.SafetyModuleV2__factory.abi).encodeFunctionData('initialize', []); await (0, util_1.waitForTx)(await safetyModuleProxyAdmin.upgradeAndCall(safetyModuleAddress, safetyModuleNewImplAddress, initializeCalldata)); (0, logging_1.log)('\n=== SAFETY MODULE FIX COMPLETE ===\n'); } exports.executeSafetyModuleUpgradeNoProposal = executeSafetyModuleUpgradeNoProposal;