UNPKG

@dydxfoundation/governance

Version:
346 lines (345 loc) 20.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.deployPhase2 = void 0; const utils_1 = require("ethers/lib/utils"); const lodash_1 = __importDefault(require("lodash")); const types_1 = require("../../types"); const StarkProxyV1__factory_1 = require("../../types/factories/StarkProxyV1__factory"); const deploy_config_1 = require("../deploy-config"); const get_deployer_address_1 = require("../deploy-config/get-deployer-address"); const constants_1 = require("../lib/constants"); const logging_1 = require("../lib/logging"); const util_1 = require("../lib/util"); const types_2 = require("../types"); const deploy_upgradeable_1 = require("./helpers/deploy-upgradeable"); const transfer_tokens_1 = require("./helpers/transfer-tokens"); async function deployPhase2({ startStep = 0, // Mock contracts. starkPerpetualAddress, dydxCollateralTokenAddress, // Phase 1 deployed contracts. dydxTokenAddress, governorAddress, shortTimelockAddress, longTimelockAddress, merklePauserTimelockAddress: merkleTimelockAddress, // Phase 2 deployed contracts. rewardsTreasuryAddress, rewardsTreasuryProxyAdminAddress, safetyModuleAddress, safetyModuleProxyAdminAddress, strategyAddress, communityTreasuryAddress, communityTreasuryProxyAdminAddress, rewardsTreasuryVesterAddress, communityTreasuryVesterAddress, claimsProxyAddress, liquidityStakingAddress, liquidityStakingProxyAdminAddress, merkleDistributorAddress, merkleDistributorProxyAdminAddress, starkProxyAddresses, starkProxyProxyAdminAddresses, }) { (0, logging_1.log)('Beginning phase 2 deployment\n'); const deployConfig = (0, deploy_config_1.getDeployConfig)(); const deployer = await (0, get_deployer_address_1.getDeployerSigner)(); const deployerAddress = deployer.address; (0, logging_1.log)(`Beginning deployment with deployer ${deployerAddress}\n`); // Phase 1 deployed contracts. const dydxToken = new types_1.DydxToken__factory(deployer).attach(dydxTokenAddress); const governor = new types_1.DydxGovernor__factory(deployer).attach(governorAddress); const longTimelock = new types_1.Executor__factory(deployer).attach(longTimelockAddress); const shortTimelock = new types_1.Executor__factory(deployer).attach(shortTimelockAddress); // Phase 2 deployed contracts. let rewardsTreasury; let rewardsTreasuryProxyAdmin; let safetyModule; let safetyModuleProxyAdmin; let strategy; let communityTreasury; let communityTreasuryProxyAdmin; let rewardsTreasuryVester; let communityTreasuryVester; let claimsProxy; let liquidityStaking; let liquidityStakingProxyAdmin; let merkleDistributor; let merkleDistributorProxyAdmin; let starkProxies; let starkProxyProxyAdmins; const deployerBalance = await dydxToken.balanceOf(deployerAddress); if (deployerBalance.lt((0, util_1.toWad)(50000000))) { throw new Error(`Need at least 500M DYDX to run this deploy script. Current balance: ${(0, utils_1.formatEther)(deployerBalance)}`); } if (startStep <= 1) { (0, logging_1.log)('Step 1. Deploy upgradeable Rewards Treasury'); [rewardsTreasury, , rewardsTreasuryProxyAdmin] = await (0, deploy_upgradeable_1.deployUpgradeable)(types_1.Treasury__factory, deployer, [], []); rewardsTreasuryAddress = rewardsTreasury.address; rewardsTreasuryProxyAdminAddress = rewardsTreasuryProxyAdmin.address; } else { if (!rewardsTreasuryAddress) { throw new Error('Expected parameter rewardsTreasuryAddress to be specified.'); } if (!rewardsTreasuryProxyAdminAddress) { throw new Error('Expected parameter rewardsTreasuryProxyAdminAddress to be specified.'); } rewardsTreasury = new types_1.Treasury__factory(deployer).attach(rewardsTreasuryAddress); rewardsTreasuryProxyAdmin = new types_1.ProxyAdmin__factory(deployer).attach(rewardsTreasuryProxyAdminAddress); } if (startStep <= 2) { (0, logging_1.log)('Step 2. Deploy and initialize upgradeable Safety Module'); [safetyModule, , safetyModuleProxyAdmin] = await (0, deploy_upgradeable_1.deployUpgradeable)(types_1.SafetyModuleV1__factory, deployer, [ dydxTokenAddress, dydxTokenAddress, rewardsTreasuryAddress, deployConfig.SM_DISTRIBUTION_START, deployConfig.SM_DISTRIBUTION_END, ], [ deployConfig.EPOCH_LENGTH, deployConfig.EPOCH_ZERO_START, deployConfig.BLACKOUT_WINDOW, ]); safetyModuleAddress = safetyModule.address; safetyModuleProxyAdminAddress = safetyModuleProxyAdmin.address; } else { if (!safetyModuleAddress) { throw new Error('Expected parameter safetyModuleAddress to be specified.'); } if (!safetyModuleProxyAdminAddress) { throw new Error('Expected parameter safetyModuleProxyAdminAddress to be specified.'); } safetyModule = new types_1.SafetyModuleV1__factory(deployer).attach(safetyModuleAddress); safetyModuleProxyAdmin = new types_1.ProxyAdmin__factory(deployer).attach(safetyModuleProxyAdminAddress); } if (startStep <= 3) { (0, logging_1.log)('Step 3. Deploy strategy'); strategy = await new types_1.GovernanceStrategy__factory(deployer).deploy(dydxTokenAddress, safetyModuleAddress); strategyAddress = strategy.address; } else { if (!strategyAddress) { throw new Error('Expected parameter strategyAddress to be specified.'); } strategy = new types_1.GovernanceStrategy__factory(deployer).attach(strategyAddress); } if (startStep <= 4) { (0, logging_1.log)('Step 4. Set strategy on governor'); await (0, util_1.waitForTx)(await governor.setGovernanceStrategy(strategyAddress)); } if (startStep <= 5) { (0, logging_1.log)('Step 5. Deploy upgradeable Community Treasury'); [communityTreasury, , communityTreasuryProxyAdmin] = await (0, deploy_upgradeable_1.deployUpgradeable)(types_1.Treasury__factory, deployer, [], []); communityTreasuryAddress = communityTreasury.address; communityTreasuryProxyAdminAddress = communityTreasuryProxyAdmin.address; } else { if (!communityTreasuryAddress) { throw new Error('Expected parameter communityTreasuryAddress to be specified.'); } if (!communityTreasuryProxyAdminAddress) { throw new Error('Expected parameter communityTreasuryProxyAdminAddress to be specified.'); } communityTreasury = new types_1.Treasury__factory(deployer).attach(communityTreasuryAddress); communityTreasuryProxyAdmin = new types_1.ProxyAdmin__factory(deployer).attach(communityTreasuryProxyAdminAddress); } if (startStep <= 6) { (0, logging_1.log)('Step 6. Deploy rewards treasury vester'); rewardsTreasuryVester = await new types_1.TreasuryVester__factory(deployer).deploy(dydxTokenAddress, rewardsTreasuryAddress, deployConfig.REWARDS_TREASURY_VESTER_CONFIG.VESTING_AMOUNT, deployConfig.REWARDS_TREASURY_VESTER_CONFIG.VESTING_BEGIN, deployConfig.REWARDS_TREASURY_VESTER_CONFIG.VESTING_CLIFF, deployConfig.REWARDS_TREASURY_VESTER_CONFIG.VESTING_END); rewardsTreasuryVesterAddress = rewardsTreasuryVester.address; } else { if (!rewardsTreasuryVesterAddress) { throw new Error('Expected parameter rewardsTreasuryVesterAddress to be specified.'); } rewardsTreasuryVester = new types_1.TreasuryVester__factory(deployer).attach(rewardsTreasuryVesterAddress); } if (startStep <= 7) { (0, logging_1.log)('Step 7. Deploy community treasury vester'); communityTreasuryVester = await new types_1.TreasuryVester__factory(deployer).deploy(dydxTokenAddress, communityTreasuryAddress, deployConfig.COMMUNITY_TREASURY_VESTER_CONFIG.VESTING_AMOUNT, deployConfig.COMMUNITY_TREASURY_VESTER_CONFIG.VESTING_BEGIN, deployConfig.COMMUNITY_TREASURY_VESTER_CONFIG.VESTING_CLIFF, deployConfig.COMMUNITY_TREASURY_VESTER_CONFIG.VESTING_END); communityTreasuryVesterAddress = communityTreasuryVester.address; } else { if (!communityTreasuryVesterAddress) { throw new Error('Expected parameter communityTreasuryVesterAddress to be specified.'); } communityTreasuryVester = new types_1.TreasuryVester__factory(deployer).attach(communityTreasuryVesterAddress); } if (startStep <= 8) { (0, logging_1.log)('Step 8. Deploy merkle distributor proxy + merkle distributor proxy admin + merkle distributor'); [merkleDistributor, , merkleDistributorProxyAdmin] = await (0, deploy_upgradeable_1.deployUpgradeable)(types_1.MerkleDistributorV1__factory, deployer, [ dydxTokenAddress, rewardsTreasuryAddress, ], [ constants_1.ZERO_ADDRESS, deployConfig.MERKLE_DISTRIBUTOR_CONFIG.IPNS_NAME, deployConfig.MERKLE_DISTRIBUTOR_CONFIG.IPFS_UPDATE_PERIOD, (0, util_1.toWad)(deployConfig.MERKLE_DISTRIBUTOR_CONFIG.MARKET_MAKER_REWARDS_AMOUNT), (0, util_1.toWad)(deployConfig.MERKLE_DISTRIBUTOR_CONFIG.TRADER_REWARDS_AMOUNT), (0, util_1.toWad)(deployConfig.MERKLE_DISTRIBUTOR_CONFIG.TRADER_SCORE_ALPHA), deployConfig.EPOCH_ZERO_START, deployConfig.EPOCH_LENGTH, ]); merkleDistributorAddress = merkleDistributor.address; merkleDistributorProxyAdminAddress = merkleDistributorProxyAdmin.address; } else { if (!merkleDistributorAddress) { throw new Error('Expected parameter merkleDistributorAddress to be specified.'); } merkleDistributor = new types_1.MerkleDistributorV1__factory(deployer).attach(merkleDistributorAddress); if (!merkleDistributorProxyAdminAddress) { throw new Error('Expected parameter merkleDistributorProxyAdminAddress to be specified.'); } merkleDistributorProxyAdmin = new types_1.ProxyAdmin__factory(deployer).attach(merkleDistributorProxyAdminAddress); } // TODO: Add steps 9–10. if (startStep <= 11) { (0, logging_1.log)('Step 11. Deploy liquidity staking proxy + liquidity staking proxy admin + liquidity staking'); [liquidityStaking, , liquidityStakingProxyAdmin] = await (0, deploy_upgradeable_1.deployUpgradeable)(types_1.LiquidityStakingV1__factory, deployer, [ dydxCollateralTokenAddress, dydxTokenAddress, rewardsTreasuryAddress, deployConfig.LS_DISTRIBUTION_START, deployConfig.LS_DISTRIBUTION_END, ], [ deployConfig.EPOCH_LENGTH, deployConfig.EPOCH_ZERO_START, deployConfig.BLACKOUT_WINDOW, ]); liquidityStakingAddress = liquidityStaking.address; liquidityStakingProxyAdminAddress = liquidityStakingProxyAdmin.address; } else { if (!liquidityStakingAddress) { throw new Error('Expected parameter liquidityStakingAddress to be specified.'); } liquidityStaking = new types_1.LiquidityStakingV1__factory(deployer).attach(liquidityStakingAddress); if (!liquidityStakingProxyAdminAddress) { throw new Error('Expected parameter liquidityStakingProxyAdminAddress to be specified.'); } liquidityStakingProxyAdmin = new types_1.ProxyAdmin__factory(deployer).attach(liquidityStakingProxyAdminAddress); } if (startStep <= 12) { (0, logging_1.log)('Step 12. Add treasury contracts token transfer allowlist'); await (0, util_1.waitForTx)(await dydxToken.addToTokenTransferAllowlist([ rewardsTreasuryAddress, communityTreasuryAddress, ])); } if (startStep <= 13) { (0, logging_1.log)('Step 13. Give incentive contracts infinite approval to pull funds from rewards treasury'); await (0, util_1.waitForTx)(await rewardsTreasury.approve(dydxTokenAddress, safetyModuleAddress, constants_1.MAX_UINT_AMOUNT)); await (0, util_1.waitForTx)(await rewardsTreasury.approve(dydxTokenAddress, merkleDistributorAddress, constants_1.MAX_UINT_AMOUNT)); await (0, util_1.waitForTx)(await rewardsTreasury.approve(dydxTokenAddress, liquidityStakingAddress, constants_1.MAX_UINT_AMOUNT)); } if (startStep <= 14) { (0, logging_1.log)('Step 14. Deploy claims proxy contract'); claimsProxy = await new types_1.ClaimsProxy__factory(deployer).deploy(safetyModuleAddress, liquidityStakingAddress, merkleDistributorAddress, rewardsTreasuryVesterAddress); claimsProxyAddress = claimsProxy.address; } else { if (!claimsProxyAddress) { throw new Error('Expected parameter claimsProxyAddress to be specified.'); } claimsProxy = new types_1.ClaimsProxy__factory(deployer).attach(claimsProxyAddress); } if (startStep <= 15) { (0, logging_1.log)('Step 15. Grant CLAIM_OPERATOR_ROLE to claims proxy for incentives contracts'); await (0, util_1.waitForTx)(await safetyModule.grantRole((0, util_1.getRole)(types_2.Role.CLAIM_OPERATOR_ROLE), claimsProxyAddress)); await (0, util_1.waitForTx)(await liquidityStaking.grantRole((0, util_1.getRole)(types_2.Role.CLAIM_OPERATOR_ROLE), claimsProxyAddress)); await (0, util_1.waitForTx)(await merkleDistributor.grantRole((0, util_1.getRole)(types_2.Role.CLAIM_OPERATOR_ROLE), claimsProxyAddress)); } if (startStep <= 16) { (0, logging_1.log)('Step 16. Set rewards rates for staking contracts'); await (0, util_1.waitForTx)(await liquidityStaking.setRewardsPerSecond(deployConfig.LS_REWARDS_PER_SECOND)); await (0, util_1.waitForTx)(await safetyModule.setRewardsPerSecond(deployConfig.SM_REWARDS_PER_SECOND)); } // TODO: Add steps 17-20. if (startStep <= 21) { // start with allocation to `ZERO_ADDRESS` set to 0 (since `ZERO_ADDRESS` initially has 100% of allocation) (0, logging_1.log)('Step 21: Deploy StarkProxies for borrowers and set borrower allocations'); const deployedStarkProxies = []; const deployedStarkProxyProxyAdmins = []; const borrowers = [constants_1.ZERO_ADDRESS]; const borrowerAllocations = [0]; for (let i = 0; i < deployConfig.STARK_PROXY_CONFIG.BORROWER_CONFIGS.length; i++) { const [starkProxy, , starkProxyProxyAdmin] = await (0, deploy_upgradeable_1.deployUpgradeable)(StarkProxyV1__factory_1.StarkProxyV1__factory, deployer, [ liquidityStakingAddress, starkPerpetualAddress, dydxCollateralTokenAddress, merkleDistributorAddress, ], [deployerAddress]); const allocation = deployConfig.STARK_PROXY_CONFIG.BORROWER_CONFIGS[i].BORROWER_ALLOCATION; deployedStarkProxies.push(starkProxy); deployedStarkProxyProxyAdmins.push(starkProxyProxyAdmin); borrowers.push(starkProxy.address); borrowerAllocations.push(allocation); } await (0, util_1.waitForTx)(await liquidityStaking.setBorrowerAllocations(borrowers, borrowerAllocations)); starkProxies = deployedStarkProxies; starkProxyProxyAdmins = deployedStarkProxyProxyAdmins; starkProxyAddresses = deployedStarkProxies.map((s) => s.address); starkProxyProxyAdminAddresses = deployedStarkProxyProxyAdmins.map((s) => s.address); } else { const numBorrowers = deployConfig.STARK_PROXY_CONFIG.BORROWER_CONFIGS.length; if (!starkProxyAddresses || starkProxyAddresses.length !== numBorrowers) { throw new Error(`Expected parameter starkProxyAddresses to be specified and have length ${numBorrowers}.`); } starkProxies = starkProxyAddresses.map((s) => new StarkProxyV1__factory_1.StarkProxyV1__factory(deployer).attach(s)); if (!starkProxyProxyAdminAddresses || starkProxyProxyAdminAddresses.length !== numBorrowers) { throw new Error(`Expected parameter starkProxyProxyAdminAddresses to be specified and have length ${numBorrowers}.`); } starkProxyProxyAdmins = starkProxyProxyAdminAddresses.map((s) => new types_1.ProxyAdmin__factory(deployer).attach(s)); } if (startStep <= 22) { (0, logging_1.log)('Step 22. Grant GUARDIAN_ROLE to short timelock, VETO_GUARDIAN_ROLE to Merkle timelock, and all other roles to borrower, for each StarkProxy'); // Revoke roles from each Stark Proxy. const starkProxyTxs = lodash_1.default.flatten(await Promise.all(starkProxies.map(async (sp, i) => { const borrowerAddress = deployConfig.STARK_PROXY_CONFIG.BORROWER_CONFIGS[i].BORROWER_ADDRESS; return [ await sp.grantRole((0, util_1.getRole)(types_2.Role.GUARDIAN_ROLE), shortTimelockAddress), await sp.grantRole((0, util_1.getRole)(types_2.Role.VETO_GUARDIAN_ROLE), merkleTimelockAddress), await sp.grantRole((0, util_1.getRole)(types_2.Role.OWNER_ROLE), borrowerAddress), await sp.grantRole((0, util_1.getRole)(types_2.Role.DELEGATION_ADMIN_ROLE), borrowerAddress), await sp.grantRole((0, util_1.getRole)(types_2.Role.WITHDRAWAL_OPERATOR_ROLE), borrowerAddress), await sp.grantRole((0, util_1.getRole)(types_2.Role.BORROWER_ROLE), borrowerAddress), await sp.grantRole((0, util_1.getRole)(types_2.Role.EXCHANGE_OPERATOR_ROLE), borrowerAddress), ]; }))); await Promise.all(starkProxyTxs.map((tx) => (0, util_1.waitForTx)(tx))); } if (startStep <= 23) { (0, logging_1.log)('Step 23. Grant contract ownership and roles to timelocks'); const txs = [ // Assign roles for the Merkle Distributor Module. await merkleDistributor.grantRole((0, util_1.getRole)(types_2.Role.PAUSER_ROLE), merkleTimelockAddress), await merkleDistributor.grantRole((0, util_1.getRole)(types_2.Role.CONFIG_UPDATER_ROLE), shortTimelockAddress), await merkleDistributor.grantRole((0, util_1.getRole)(types_2.Role.OWNER_ROLE), shortTimelockAddress), await merkleDistributor.grantRole((0, util_1.getRole)(types_2.Role.UNPAUSER_ROLE), shortTimelockAddress), // Assign roles for the Liquidity Staking Module. await liquidityStaking.grantRole((0, util_1.getRole)(types_2.Role.OWNER_ROLE), shortTimelockAddress), await liquidityStaking.grantRole((0, util_1.getRole)(types_2.Role.EPOCH_PARAMETERS_ROLE), shortTimelockAddress), await liquidityStaking.grantRole((0, util_1.getRole)(types_2.Role.REWARDS_RATE_ROLE), shortTimelockAddress), await liquidityStaking.grantRole((0, util_1.getRole)(types_2.Role.BORROWER_ADMIN_ROLE), shortTimelockAddress), // Assign roles for the Safety Module. await safetyModule.grantRole((0, util_1.getRole)(types_2.Role.OWNER_ROLE), shortTimelockAddress), await safetyModule.grantRole((0, util_1.getRole)(types_2.Role.SLASHER_ROLE), shortTimelockAddress), await safetyModule.grantRole((0, util_1.getRole)(types_2.Role.EPOCH_PARAMETERS_ROLE), shortTimelockAddress), await safetyModule.grantRole((0, util_1.getRole)(types_2.Role.REWARDS_RATE_ROLE), shortTimelockAddress), // Assign roles for the Governor. await governor.grantRole((0, util_1.getRole)(types_2.Role.OWNER_ROLE), longTimelock.address), await governor.grantRole((0, util_1.getRole)(types_2.Role.ADD_EXECUTOR_ROLE), shortTimelock.address), ]; await Promise.all(txs.map((tx) => (0, util_1.waitForTx)(tx))); } if (startStep <= 24) { (0, logging_1.log)('Step 24. Send tokens to rewards treasury'); await (0, transfer_tokens_1.transferWithPrompt)(dydxToken, rewardsTreasuryAddress, deployConfig.REWARDS_TREASURY_FRONTLOADED_FUNDS); } (0, logging_1.log)('\n=== PHASE 2 DEPLOYMENT COMPLETE ===\n'); return { rewardsTreasury, rewardsTreasuryProxyAdmin, safetyModule, safetyModuleProxyAdmin, strategy, communityTreasury, communityTreasuryProxyAdmin, rewardsTreasuryVester, communityTreasuryVester, claimsProxy, liquidityStaking, liquidityStakingProxyAdmin, merkleDistributor, merkleDistributorProxyAdmin, starkProxies, starkProxyProxyAdmins, }; } exports.deployPhase2 = deployPhase2;