diff --git a/block.txt b/block.txt index d421535af..07a70fc50 100644 --- a/block.txt +++ b/block.txt @@ -1 +1 @@ -15746734 \ No newline at end of file +15825392 diff --git a/contracts/test/integration/fixtures/MainnetAddresses.sol b/contracts/test/integration/fixtures/MainnetAddresses.sol index 627c4c76a..70900eed8 100644 --- a/contracts/test/integration/fixtures/MainnetAddresses.sol +++ b/contracts/test/integration/fixtures/MainnetAddresses.sol @@ -57,4 +57,5 @@ library MainnetAddresses { address public constant RARI_TRIBE_TOKEN_TIMELOCK = 0x625cf6AA7DafB154F3Eb6BE87592110e30290dEe; address public constant FEI_LABS_CONTRACT = 0x38AfBF8128cc54323e216ACde9516d281c4F1E5f; address public constant TRIBE_FEI_LABS_DEL = 0x66b9D411E14FBc86424367b67933945fd7E40B11; + address public constant TRIBE_FEI_LABS_DEL_2 = 0xb81cf4981Ef648aaA73F07a18B03970f04d5D8bF; } diff --git a/contracts/test/integration/shutdown/timelocks/TribeTimelockedDelegatorBurner.t.sol b/contracts/test/integration/shutdown/timelocks/TribeTimelockedDelegatorBurner.t.sol index 8e9aa8f41..1837471f3 100644 --- a/contracts/test/integration/shutdown/timelocks/TribeTimelockedDelegatorBurner.t.sol +++ b/contracts/test/integration/shutdown/timelocks/TribeTimelockedDelegatorBurner.t.sol @@ -27,8 +27,10 @@ contract TribeTimelockedDelegatorBurnerIntegrationTest is DSTest { tribeTimelock.setPendingBeneficiary(address(tribeTimelockBurner)); // Undelegate some TRIBE to make enough available for withdrawals - vm.prank(tribeTimelock.beneficiary()); + vm.startPrank(tribeTimelock.beneficiary()); tribeTimelock.undelegate(MainnetAddresses.TRIBE_FEI_LABS_DEL); + tribeTimelock.undelegate(MainnetAddresses.TRIBE_FEI_LABS_DEL_2); + vm.stopPrank(); } /// @notice Validate that timelock to burn is setup diff --git a/proposals/dao/old/phase_1.ts b/proposals/dao/old/phase_1.ts index 49667cfa2..5249c3d73 100644 --- a/proposals/dao/old/phase_1.ts +++ b/proposals/dao/old/phase_1.ts @@ -118,7 +118,7 @@ const validate: ValidateUpgradeFunc = async (addresses, oldContracts, contracts, expect(await contracts.uniswapLiquidityRemover.FEI_TRIBE_PAIR()).to.be.equal(addresses.feiTribePair); // 3. Validate Fei Labs vesting timelock accepted beneficiary - expect(await contracts.feiLabsVestingTimelock.beneficiary()).to.be.equal(addresses.feiDAOTimelock); + expect(await contracts.tribeDAODelegationsTimelock.beneficiary()).to.be.equal(addresses.feiDAOTimelock); // 4. Uniswap LP liquidity timelock should have no LP tokens or FEI or TRIBE expect(await contracts.feiTribePair.balanceOf(addresses.uniswapFeiTribeLiquidityTimelock)).to.be.equal(0); diff --git a/proposals/dao/tip_123.ts b/proposals/dao/tip_123.ts new file mode 100644 index 000000000..32a3fdec1 --- /dev/null +++ b/proposals/dao/tip_123.ts @@ -0,0 +1,225 @@ +import { ethers } from 'hardhat'; +import { expect } from 'chai'; +import { + DeployUpgradeFunc, + NamedAddresses, + NamedContracts, + PcvStats, + SetupUpgradeFunc, + TeardownUpgradeFunc, + ValidateUpgradeFunc +} from '@custom-types/types'; +import { forceEth } from '@test/integration/setup/utils'; +import { getImpersonatedSigner, time } from '@test/helpers'; +import { BigNumber } from 'ethers'; + +/* + +TIP_123 + +*/ + +let pcvStatsBefore: PcvStats; +let initialTotalTribeDelegation: BigNumber; + +const fipNumber = 'tip_123'; + +// Do any deployments +// This should exclusively include new contract deployments +const deploy: DeployUpgradeFunc = async (deployAddress: string, addresses: NamedAddresses, logging: boolean) => { + // 1. Deploy DAOTimelockBurner, to burn admin of Fei and Rari DAO timelocks + const DAOTimelockBurnerFactory = await ethers.getContractFactory('DAOTimelockBurner'); + const daoTimelockBurner = await DAOTimelockBurnerFactory.deploy(); + console.log('DAO timelock burner deployed to: ', daoTimelockBurner.address); + + const FeiTimelockBurnerFactory = await ethers.getContractFactory('FeiLinearTokenTimelockBurner'); + // 2. Deploy deprecated Rari FEI timelock burner + const feiTimelockBurner1 = await FeiTimelockBurnerFactory.deploy(addresses.rariInfraFeiTimelock); + console.log('Deprecated Rari FEI timelock burner deployed to: ', feiTimelockBurner1.address); + + // 3. Deploy deprecated Rari TRIBE timelock burner + const TribeTimelockedDelegatorBurnerFactory = await ethers.getContractFactory('TribeTimelockedDelegatorBurner'); + const tribeTimelockBurner1 = await TribeTimelockedDelegatorBurnerFactory.deploy(addresses.rariInfraTribeTimelock); + console.log('Deprecated Rari TRIBE timelock burned deployed to: ', tribeTimelockBurner1.address); + + // 4. Deploy Fei Labs burner + const tribeTimelockBurner2 = await TribeTimelockedDelegatorBurnerFactory.deploy( + addresses.tribeDAODelegationsTimelock + ); + console.log('Tribe DAO delegations TRIBE burner deployed to: ', tribeTimelockBurner2.address); + + return { + daoTimelockBurner, + feiTimelockBurner1, + tribeTimelockBurner1, + tribeTimelockBurner2 + }; +}; + +// Do any setup necessary for running the test. +// This could include setting up Hardhat to impersonate accounts, +// ensuring contracts have a specific state, etc. +const setup: SetupUpgradeFunc = async (addresses, oldContracts, contracts, logging) => { + pcvStatsBefore = await contracts.collateralizationOracle.pcvStats(); + initialTotalTribeDelegation = await contracts.tribeDAODelegationsTimelock.totalDelegated(); +}; + +// Tears down any changes made in setup() that need to be +// cleaned up before doing any validation checks. +const teardown: TeardownUpgradeFunc = async (addresses, oldContracts, contracts, logging) => { + console.log(`No actions to complete in teardown for fip${fipNumber}`); +}; + +// Run any validations required on the fip using mocha or console logging +// IE check balances, check state of contracts, etc. +const validate: ValidateUpgradeFunc = async (addresses, oldContracts, contracts, logging) => { + // display pcvStats + console.log('----------------------------------------------------'); + console.log(' pcvStatsBefore.protocolControlledValue [M]e18 ', Number(pcvStatsBefore.protocolControlledValue) / 1e24); + console.log(' pcvStatsBefore.userCirculatingFei [M]e18 ', Number(pcvStatsBefore.userCirculatingFei) / 1e24); + console.log(' pcvStatsBefore.protocolEquity [M]e18 ', Number(pcvStatsBefore.protocolEquity) / 1e24); + const pcvStatsAfter: PcvStats = await contracts.collateralizationOracle.pcvStats(); + console.log('----------------------------------------------------'); + console.log(' pcvStatsAfter.protocolControlledValue [M]e18 ', Number(pcvStatsAfter.protocolControlledValue) / 1e24); + console.log(' pcvStatsAfter.userCirculatingFei [M]e18 ', Number(pcvStatsAfter.userCirculatingFei) / 1e24); + console.log(' pcvStatsAfter.protocolEquity [M]e18 ', Number(pcvStatsAfter.protocolEquity) / 1e24); + console.log('----------------------------------------------------'); + const pcvDiff = pcvStatsAfter.protocolControlledValue.sub(pcvStatsBefore.protocolControlledValue); + const cFeiDiff = pcvStatsAfter.userCirculatingFei.sub(pcvStatsBefore.userCirculatingFei); + const eqDiff = pcvStatsAfter.protocolEquity.sub(pcvStatsBefore.protocolEquity); + console.log(' PCV diff [M]e18 ', Number(pcvDiff) / 1e24); + console.log(' Circ FEI diff [M]e18 ', Number(cFeiDiff) / 1e24); + console.log(' Equity diff [M]e18 ', Number(eqDiff) / 1e24); + console.log('----------------------------------------------------'); + + // 0. Assert overcollaterised + expect(await contracts.collateralizationOracle.isOvercollateralized()).to.be.true; + + // 1. Verify Fei DAO timelock admin burned + expect(await contracts.feiDAOTimelock.admin()).to.equal(addresses.daoTimelockBurner); + + // Verify no addresses have GOVERN_ROLE, GUARDIAN_ROLE. One has PCV_CONTROLLER_ROLE, one has MINTER + expect(await contracts.core.getRoleMemberCount(ethers.utils.id('GOVERN_ROLE'))).to.equal(0); + expect(await contracts.core.getRoleMemberCount(ethers.utils.id('GUARDIAN_ROLE'))).to.equal(0); + expect(await contracts.core.getRoleMemberCount(ethers.utils.id('PCV_CONTROLLER_ROLE'))).to.equal(1); + expect(await contracts.core.getRoleMemberCount(ethers.utils.id('MINTER_ROLE'))).to.equal(1); + + // 2. Verify Rari Fei deprecated timelock burned + expect(await contracts.rariInfraFeiTimelock.beneficiary()).to.equal(addresses.feiTimelockBurner1); + + // 3. Verify Rari Tribe deprecated timelock burned + expect(await contracts.rariInfraTribeTimelock.beneficiary()).to.equal(addresses.tribeTimelockBurner1); + + // Verify Fuse multisig does not have any delegated TRIBE + expect(await contracts.tribe.getCurrentVotes(addresses.fuseMultisig)).to.equal(0); + + // 4. Verify Tribe DAO Delegations timelock burned + expect(await contracts.tribeDAODelegationsTimelock.beneficiary()).to.equal(addresses.tribeTimelockBurner2); + + // 5. Verify Tribe minter set to zero address and inflation is the minimum of 0.01% (1 basis point) + expect(await contracts.tribe.minter()).to.equal(ethers.constants.AddressZero); + expect(await contracts.tribeMinter.annualMaxInflationBasisPoints()).to.equal(1); + + // 6. Verify can not queue on DAO timelock + await verifyCanNotQueueProposals(contracts, addresses); + + // 7. Verify proxyAdmin ownership renounced + expect(await contracts.proxyAdmin.owner()).to.equal(ethers.constants.AddressZero); + + // 8. Verify can permissionlessly undelegated TRIBE from timelock via TRIBE timelock burner + const delegatee = '0x0d4ba14ca1e990654c6f9c7957b9b23f8a1429dc'; + const expectedDelegateeDelegation = ethers.constants.WeiPerEther.mul(1_000_000); + expect(await contracts.tribeDAODelegationsTimelock.delegateAmount(delegatee)).to.equal(expectedDelegateeDelegation); + + await contracts.tribeTimelockBurner2.undelegate(delegatee); + + const finalTribeDelegated = await contracts.tribeDAODelegationsTimelock.totalDelegated(); + const undelegatedAmount = initialTotalTribeDelegation.sub(finalTribeDelegated); + + // Verify delegatee no longer has a delegation + expect(await contracts.tribeDAODelegationsTimelock.delegateAmount(delegatee)).to.equal(0); + + // Verify total delegation decrease was equal to the delegates delegation + expect(undelegatedAmount).to.equal(expectedDelegateeDelegation); + + // 9. Verify can permissionlessly burn FEI on Rari infra burner timelock + const initialFeiSupply = await contracts.fei.totalSupply(); + const initialRariTimelockFei = await contracts.fei.balanceOf(addresses.rariInfraFeiTimelock); + await contracts.feiTimelockBurner1.burnFeiHeld(); + const feiBurned = initialFeiSupply.sub(await contracts.fei.totalSupply()); + const rariTimelockFeiLoss = initialRariTimelockFei.sub(await contracts.fei.balanceOf(addresses.rariInfraFeiTimelock)); + expect(feiBurned).to.equal(rariTimelockFeiLoss); + + // 10. Verify can permissionlessly sendTribeToTreasury() on Rari infra Tribe burner timelock + const initialCoreTreasury1 = await contracts.tribe.balanceOf(addresses.core); + const initialRariTimelockTribe1 = await contracts.tribe.balanceOf(addresses.rariInfraTribeTimelock); + await contracts.tribeTimelockBurner1.sendTribeToTreaury(); + const rariTimelockTribeLoss1 = initialRariTimelockTribe1.sub( + await contracts.tribe.balanceOf(addresses.rariInfraTribeTimelock) + ); + const coreTreasuryGain1 = (await contracts.tribe.balanceOf(addresses.core)).sub(initialCoreTreasury1); + expect(coreTreasuryGain1).to.equal(rariTimelockTribeLoss1); + + // 11. Verify can permissionlessly sendTribeToTreasury() on Tribe DAO delegations burner timelock + // Undelegate TRIBE to make available + await contracts.tribeTimelockBurner2.undelegate('0xd046135ba00b0315ed4c3135206c87a7f4eb57d9'); + await contracts.tribeTimelockBurner2.undelegate('0xc64ed730e030bdcb66e9b5703798bb4275a5a484'); + await contracts.tribeTimelockBurner2.undelegate('0x114b8d7ab033e650003fa3fc72c5ba2d0fd18345'); + + const initialCoreTreasury2 = await contracts.tribe.balanceOf(addresses.core); + const initialDAOTimelockTribe2 = await contracts.tribe.balanceOf(addresses.tribeDAODelegationsTimelock); + await contracts.tribeTimelockBurner2.sendTribeToTreaury(); + const daoTimelockTribeLoss2 = initialDAOTimelockTribe2.sub( + await contracts.tribe.balanceOf(addresses.tribeDAODelegationsTimelock) + ); + const coreTreasuryGain2 = (await contracts.tribe.balanceOf(addresses.core)).sub(initialCoreTreasury2); + expect(coreTreasuryGain2).to.equal(daoTimelockTribeLoss2); +}; + +// Verify proposals can not be queued +const verifyCanNotQueueProposals = async (contracts: NamedContracts, addresses: NamedAddresses) => { + const feiDAO = contracts.feiDAO; + + const targets = [feiDAO.address]; + const values = [0]; + const calldatas = [ + '0x70b0f660000000000000000000000000000000000000000000000000000000000000000a' // set voting delay 10 + ]; + const description: any[] = []; + + const treasurySigner = await getImpersonatedSigner(addresses.core); + await forceEth(addresses.core); + await contracts.tribe.connect(treasurySigner).delegate(addresses.guardianMultisig); + const signer = await getImpersonatedSigner(addresses.guardianMultisig); + + // Propose + // note ethers.js requires using this notation when two overloaded methods exist) + // https://docs.ethers.io/v5/migration/web3/#migration-from-web3-js--contracts--overloaded-functions + await feiDAO.connect(signer)['propose(address[],uint256[],bytes[],string)'](targets, values, calldatas, description); + + const pid = await feiDAO.hashProposal(targets, values, calldatas, ethers.utils.keccak256(description)); + + await time.advanceBlock(); + + // vote + await feiDAO.connect(signer).castVote(pid, 1); + + // advance to end of voting period + const endBlock = (await feiDAO.proposals(pid)).endBlock; + await time.advanceBlockTo(endBlock.toNumber()); + + expect(await contracts.feiDAO.state(pid)).to.equal(4); // SUCCEEDED state in ProposalState enum + + // Attempt to queue on the timelock through the Fei DAO + // Queuing should fail as daoTimelockBurner is admin of timelock + await expect( + feiDAO['queue(address[],uint256[],bytes[],bytes32)']( + targets, + values, + calldatas, + ethers.utils.keccak256(description) + ) + ).to.be.revertedWith('Timelock: Call must come from admin.'); +}; + +export { deploy, setup, teardown, validate }; diff --git a/proposals/description/old/phase_1.ts b/proposals/description/old/phase_1.ts index 034d436fc..da7e2b06e 100644 --- a/proposals/description/old/phase_1.ts +++ b/proposals/description/old/phase_1.ts @@ -12,7 +12,7 @@ const phase_1: TemplatedProposalDescription = { commands: [ // 1. Accept the beneficiary of Fei Labs vesting TRIBE timelock contract as the DAO timelock { - target: 'feiLabsVestingTimelock', + target: 'tribeDAODelegationsTimelock', values: '0', method: 'acceptBeneficiary()', arguments: (addresses) => [], diff --git a/proposals/description/tip_123.ts b/proposals/description/tip_123.ts new file mode 100644 index 000000000..1c78145a6 --- /dev/null +++ b/proposals/description/tip_123.ts @@ -0,0 +1,166 @@ +import { TemplatedProposalDescription } from '@custom-types/types'; +import { ethers } from 'ethers'; + +const tip_123: TemplatedProposalDescription = { + title: 'TIP-121: Proposal for the future of the Tribe DAO', + commands: [ + // 1. Transfer beneficiary of deprecated Rari FEI timelock to burner timelock + { + target: 'rariInfraFeiTimelock', + values: '0', + method: 'setPendingBeneficiary(address)', + arguments: (addresses) => [addresses.feiTimelockBurner1], + description: 'Set pending beneficiary of deprecated Rari Fei timelock burner to Fei burner timelock' + }, + { + target: 'feiTimelockBurner1', + values: '0', + method: 'acceptBeneficiary()', + arguments: (addresses) => [], + description: 'Accept deprecated Rari Fei timelock beneficiary to burner' + }, + + // 2. Transfer beneficiary of deprecated Rari TRIBE timelock to burner timelock + { + target: 'rariInfraTribeTimelock', + values: '0', + method: 'delegate(address)', + arguments: (addresses) => [ethers.constants.AddressZero], + description: 'Delegate all voting TRIBE to the ZERO address' + }, + { + target: 'rariInfraTribeTimelock', + values: '0', + method: 'setPendingBeneficiary(address)', + arguments: (addresses) => [addresses.tribeTimelockBurner1], + description: 'Set pending beneficiary of deprecated Rari Tribe timelock to Tribe burner timelock' + }, + { + target: 'tribeTimelockBurner1', + values: '0', + method: 'acceptBeneficiary()', + arguments: (addresses) => [], + description: 'Accept deprecated Rari Tribe timelock beneficiary to burner' + }, + + // 3. Transfer beneficiary of Tribe DAO delegations contract to burner TRIBE timelock + { + target: 'tribeDAODelegationsTimelock', + values: '0', + method: 'setPendingBeneficiary(address)', + arguments: (addresses) => [addresses.tribeTimelockBurner2], + description: ` + Set pending beneficiary of Tribe DAO Tribe delegations timelock to Tribe DAO delegations + TRIBE burner timelock + ` + }, + { + target: 'tribeTimelockBurner2', + values: '0', + method: 'acceptBeneficiary()', + arguments: (addresses) => [], + description: 'Accept deprecated Tribe DAO delegations TRIBE timelock beneficiary to burner' + }, + + // 3. Deprecate TribeMinter + { + target: 'tribeMinter', + values: '0', + method: 'setAnnualMaxInflationBasisPoints(uint256)', + arguments: (addresses) => ['1'], + description: 'Set Tribe minter max annual inflation to the minimum of 0.01% (1 basis point)' + }, + { + target: 'tribeMinter', + values: '0', + method: 'setMinter(address)', + arguments: (addresses) => [addresses.feiDAOTimelock], + description: ` + Set Tribe minter address to DAO timelock. This is an intermediate step and a subsequent action + will set the minter address to the zero address, effectively burning it (Tribe Minter doesn't allow + setting to zero). + ` + }, + { + target: 'tribe', + values: '0', + method: 'setMinter(address)', + arguments: (addresses) => [ethers.constants.AddressZero], + description: 'Set Tribe minter address to the Zero address' + }, + + // 4. Revoke PCV_CONTROLLER_ROLE from the DAO + { + target: 'core', + values: '0', + method: 'revokeRole(bytes32,address)', + arguments: (addresses) => [ethers.utils.id('PCV_CONTROLLER_ROLE'), addresses.feiDAOTimelock], + description: 'Revoke the PCV_CONTROLLER_ROLE from the TribeDAO timelock' + }, + + // 5. Revoke GUARDIAN role from Guardian multisig + { + target: 'core', + values: '0', + method: 'revokeRole(bytes32,address)', + arguments: (addresses) => [ethers.utils.id('GUARDIAN_ROLE'), addresses.guardianMultisig], + description: 'Revoke the GUARDIAN_ROLE from the Guardian multisig' + }, + + // 6. Revoke GOVERN_ROLE from the DAO and Core + { + target: 'core', + values: '0', + method: 'revokeRole(bytes32,address)', + arguments: (addresses) => [ethers.utils.id('GOVERN_ROLE'), addresses.core], + description: 'Revoke the GOVERN_ROLE from the Core Treasury' + }, + { + target: 'core', + values: '0', + method: 'revokeRole(bytes32,address)', + arguments: (addresses) => [ethers.utils.id('GOVERN_ROLE'), addresses.feiDAOTimelock], + description: 'Revoke the GOVERN_ROLE from the TribeDAO timelock' + }, + + // 7. Renounce ownership of ProxyAdmin + { + target: 'proxyAdmin', + values: '0', + method: 'renounceOwnership()', + arguments: (addresses) => [], + description: 'Renounce ownership of ProxyAdmin, transferring owner to zero address' + }, + + // 8. Transfer admin of DAO timelock to DAO timelock burner + { + target: 'feiDAOTimelock', + values: '0', + method: 'setPendingAdmin(address)', + arguments: (addresses) => [addresses.daoTimelockBurner], + description: 'Set pending Fei DAO timelock admin to be the DAO timelock burner' + }, + { + target: 'daoTimelockBurner', + values: '0', + method: 'acceptFeiDAOTimelockAdmin()', + arguments: (addresses) => [], + description: 'Accept Fei DAO timelock admin transfer to the DAO timelock burner' + } + ], + description: ` +TIP-121: Proposal for the future of the Tribe DAO + +This is a completion of the proposal laid out in TIP-121: https://tribe.fei.money/t/tip-121-proposal-for-the-future-of-the-tribe-dao/4475 + +It transitions the DAO to a governance-less state by disabling the functionality by which the DAO executes proposals. + +In addition, it disables new TRIBE minting, consolidates all DAO owned TRIBE and FEI, and revokes all roles remaining including the GOVERNOR and GUARDIAN roles. + +The only remaining roles will be the single MINTER_ROLE on the FEI to DAI peg wrapper contract and the roles Aave needs to operate the OTC contract from “TIP-121c: veBAL OTC with Aave Companies”. Both of these roles need to remain in perpetuity to maintain basic functionality. + +TRIBE and FEI will continue to remain redeemable on the TribeRedeemer and SimpleFeiDaiPSM respectively if this proposal passes. + ` +}; + +export default tip_123; diff --git a/protocol-configuration/mainnetAddresses.ts b/protocol-configuration/mainnetAddresses.ts index c4c77b6af..b9d35d82b 100644 --- a/protocol-configuration/mainnetAddresses.ts +++ b/protocol-configuration/mainnetAddresses.ts @@ -26,264 +26,57 @@ export const MainnetContractsConfig = { address: '0x956F47F50A910163D8BF957Cf5846D573E7f87CA', category: AddressCategory.Core }, - proxyAdmin: { - artifactName: 'ProxyAdmin', - address: '0xf8c2b645988b7658E7748BA637fE25bdD46A704A', - category: AddressCategory.Core - }, tribe: { artifactName: 'Tribe', address: '0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B', category: AddressCategory.Core }, - tribeMinter: { - artifactName: 'TribeMinter', - address: '0xFC3532b443383d9022b1B2c6FD5Fd0895943360A', - category: AddressCategory.Core - }, restrictedPermissions: { artifactName: 'RestrictedPermissions', address: '0x10ffa0CD36Bc16b355d21A08DF4a552c4A9FEC10', category: AddressCategory.Core }, + daoTimelockBurner: { + artifactName: 'DAOTimelockBurner', + address: '0x6F6580285a63f1e886548458f427f8695BA1a563', + category: AddressCategory.Core + }, feiTimelockBurner1: { artifactName: 'FeiLinearTokenTimelockBurner', address: '0x072e5D8DBe245bB78aF1888866E6eFE9548d017F', category: AddressCategory.Distribution }, + rariInfraFeiTimelock: { + artifactName: 'LinearTokenTimelock', + address: '0xfaFC562265a49975E8B20707EAC966473795CF90', + category: AddressCategory.Distribution + }, tribeTimelockBurner1: { artifactName: 'TribeTimelockedDelegatorBurner', address: '0x8772D97229A55cf0e2D4AB37766D5DC5647cdF3C', category: AddressCategory.Distribution }, + rariInfraTribeTimelock: { + artifactName: 'LinearTimelockedDelegator', + address: '0x625cf6AA7DafB154F3Eb6BE87592110e30290dEe', + category: AddressCategory.Distribution + }, tribeTimelockBurner2: { artifactName: 'TribeTimelockedDelegatorBurner', address: '0x8f966aF3ACc936aE6b8ebeB893F6f5925e220902', category: AddressCategory.Distribution }, - daoTimelockBurner: { - artifactName: 'DAOTimelockBurner', - address: '0x6F6580285a63f1e886548458f427f8695BA1a563', - category: AddressCategory.Core - }, - guardianMultisig: { - artifactName: 'unknown', - address: '0xB8f482539F2d3Ae2C9ea6076894df36D1f632775', - category: AddressCategory.Security - }, - feiDAO: { - artifactName: 'FeiDAO', - address: '0x0BEF27FEB58e857046d630B2c03dFb7bae567494', - category: AddressCategory.Governance - }, - - feiDAOTimelock: { - artifactName: 'FeiDAOTimelock', - address: '0xd51dbA7a94e1adEa403553A8235C302cEbF41a3c', - category: AddressCategory.Governance - }, - rariTimelock: { - artifactName: 'Timelock', - address: '0x8ace03Fc45139fDDba944c6A4082b604041d19FC', - category: AddressCategory.Governance - }, - - tribeRariDAO: { - artifactName: 'FeiDAO', - address: '0x637deEED4e4deb1D222650bD4B64192abf002c00', - category: AddressCategory.Governance - }, - - rariGovernanceProxyAdmin: { - artifactName: 'ProxyAdmin', - address: '0x1c9aA54a013962C2444ECae06902F31D532c6AD3', - category: AddressCategory.Governance - }, - - rariTimelockFeiOldLens: { - artifactName: 'ERC20PCVDepositWrapper', - address: '0x614D46B7eB2AC1a359b8835D64954F3Ee4E6F676', - category: AddressCategory.PCV + tribeDAODelegationsTimelock: { + artifactName: 'TimelockedDelegator', + address: '0x38afbf8128cc54323e216acde9516d281c4f1e5f', + category: AddressCategory.Distribution }, - escrowedAaveDaiPCVDeposit: { artifactName: 'ERC20PCVDepositWrapper', address: '0x82c55A1Ab5C6F4b8e162b7dE24b50A38E1aFd38f', category: AddressCategory.PCV }, - collateralizationOracle: { - artifactName: 'CollateralizationOracle', - address: '0xFF6f59333cfD8f4Ebc14aD0a0E181a83e655d257', - category: AddressCategory.Collateralization - }, - rariInfraFeiTimelock: { - artifactName: 'LinearTokenTimelock', - address: '0xfaFC562265a49975E8B20707EAC966473795CF90', - category: AddressCategory.Distribution - }, - rariInfraTribeTimelock: { - artifactName: 'LinearTimelockedDelegator', - address: '0x625cf6AA7DafB154F3Eb6BE87592110e30290dEe', - category: AddressCategory.Distribution - }, - - oneConstantOracle: { - artifactName: 'ConstantOracle', - address: '0x2374800337c6BE8B935f96AA6c10b33f9F12Bd40', - category: AddressCategory.Oracle - }, - - zeroConstantOracle: { - artifactName: 'ConstantOracle', - address: '0x43b99923CF06D6D9101110b595234670f73A4934', - category: AddressCategory.Oracle - }, - - rariPool8ConvexD3Plugin: { - artifactName: 'IConvexERC4626', - address: '0xaa189e7f4aac757216b62849f78f1236749ba814', - category: AddressCategory.FeiRari - }, - - rariCErc20PluginImpl: { - artifactName: 'unknown', - address: '0xbfb8D550B53F64F581df1Da41DDa0CB9E596Aa0E', - category: AddressCategory.FeiRari - }, - - rariPool8Comptroller: { - artifactName: 'Unitroller', - address: '0xc54172e34046c1653d1920d40333dd358c7a1af4', - category: AddressCategory.FeiRari - }, - - rariPool8MasterOracle: { - artifactName: 'IMasterOracle', - address: '0x4d10BC156FBaD2474a94f792fe0D6c3261469cdd', - category: AddressCategory.FeiRari - }, - - rariChainlinkPriceOracleV3: { - artifactName: 'unknown', - address: '0x058c345D3240001088b6280e008F9e78b3B2112d', - category: AddressCategory.FeiRari - }, - - curveLPTokenOracle: { - artifactName: 'unknown', - address: '0xa9f3faac3b8eDF7b3DCcFDBBf25033D6F5fc02F3', - category: AddressCategory.FeiRari - }, - - gUniFuseOracle: { - artifactName: 'unknown', - address: '0xEa3633b38C747ceA231aDB74b511DC2eD3992B43', - category: AddressCategory.FeiRari - }, - - rariPool8Lusd: { - artifactName: 'CErc20Delegator', - address: '0x647A36d421183a0a9Fa62717a64B664a24E469C7', - category: AddressCategory.FeiRari - }, - - rariPool8Dai: { - artifactName: 'CErc20Delegator', - address: '0x7e9cE3CAa9910cc048590801e64174957Ed41d43', - category: AddressCategory.FeiRari - }, - - rariPool8DaiIrm: { - artifactName: 'unknown', - address: '0xede47399e2aa8f076d40dc52896331cba8bd40f7', - category: AddressCategory.FeiRari - }, - - rariPool8Eth: { - artifactName: 'CErc20Delegator', - address: '0xbB025D470162CC5eA24daF7d4566064EE7f5F111', - category: AddressCategory.FeiRari - }, - - rariPool8EthIrm: { - artifactName: 'unknown', - address: '0xbab47e4b692195bf064923178a90ef999a15f819', - category: AddressCategory.FeiRari - }, - - rariPool8Fei: { - artifactName: 'CErc20Delegator', - address: '0xd8553552f8868C1Ef160eEdf031cF0BCf9686945', - category: AddressCategory.FeiRari - }, - - rariPool8FeiIrm: { - artifactName: 'unknown', - address: '0x8f47be5692180079931e2f983db6996647aba0a5', - category: AddressCategory.FeiRari - }, - - rariPool8Tribe: { - artifactName: 'CErc20Delegator', - address: '0xFd3300A9a74b3250F1b2AbC12B47611171910b07', - category: AddressCategory.FeiRari - }, - - rariPool8TribeIrm: { - artifactName: 'unknown', - address: '0x075538650a9c69ac8019507a7dd1bd879b12c1d7', - category: AddressCategory.FeiRari - }, - - rariPool8CTokenImpl: { - artifactName: 'unknown', - address: '0x67Db14E73C2Dce786B5bbBfa4D010dEab4BBFCF9', - category: AddressCategory.FeiRari - }, - - rariPool8Fei3Crv: { - artifactName: 'CErc20Delegator', - address: '0xBFB6f7532d2DB0fE4D83aBb001c5C2B0842AF4dB', - category: AddressCategory.FeiRari - }, - - rariPool8FeiD3: { - artifactName: 'CErc20Delegator', - address: '0x5cA8Ffe4DAD9452ED880FA429DD0A08574225936', - category: AddressCategory.FeiRari - }, - - rariPool146Comptroller: { - artifactName: 'Unitroller', - address: '0x88F7c23EA6C4C404dA463Bc9aE03b012B32DEf9e', - category: AddressCategory.FeiRari - }, - - rariPool146FuseAdmin: { - artifactName: 'FuseAdmin', - address: '0x6d64D080345C446dA31b8D3855bA6d9C0fC875D2', - category: AddressCategory.FeiRari - }, - - rariPool146Eth: { - artifactName: 'unknown', - address: '0xfbD8Aaf46Ab3C2732FA930e5B343cd67cEA5054C', - category: AddressCategory.FeiRari - }, - - fuseAdmin: { - artifactName: 'FuseAdmin', - address: '0x761dD1Ae03D95BdABeC3C228532Dcdab4F2c7adD', - category: AddressCategory.FeiRari - }, - - fuseGuardian: { - artifactName: 'FuseGuardian', - address: '0xc0c59A2d3F278445f27ed4a00E2727D6c677c43F', - category: AddressCategory.FeiRari - }, - balancerBBaUSD: { artifactName: 'unknown', address: '0xA13a9247ea42D743238089903570127DdA72fE44', @@ -1212,7 +1005,8 @@ export const MainnetContractsConfig = { }, fishy: { artifactName: 'unknown', - address: '0x7D82675470B06453980b37880d81f6F254371FD3' + address: '0x7D82675470B06453980b37880d81f6F254371FD3', + category: AddressCategory.External }, wintermute: { artifactName: 'unknown', @@ -1236,6 +1030,219 @@ export const MainnetContractsConfig = { category: AddressCategory.External }, + oneConstantOracle: { + artifactName: 'ConstantOracle', + address: '0x2374800337c6BE8B935f96AA6c10b33f9F12Bd40', + category: AddressCategory.External + }, + + zeroConstantOracle: { + artifactName: 'ConstantOracle', + address: '0x43b99923CF06D6D9101110b595234670f73A4934', + category: AddressCategory.External + }, + + rariPool8ConvexD3Plugin: { + artifactName: 'IConvexERC4626', + address: '0xaa189e7f4aac757216b62849f78f1236749ba814', + category: AddressCategory.External + }, + + rariCErc20PluginImpl: { + artifactName: 'unknown', + address: '0xbfb8D550B53F64F581df1Da41DDa0CB9E596Aa0E', + category: AddressCategory.External + }, + + rariPool8Comptroller: { + artifactName: 'Unitroller', + address: '0xc54172e34046c1653d1920d40333dd358c7a1af4', + category: AddressCategory.External + }, + + rariPool8MasterOracle: { + artifactName: 'IMasterOracle', + address: '0x4d10BC156FBaD2474a94f792fe0D6c3261469cdd', + category: AddressCategory.External + }, + + rariChainlinkPriceOracleV3: { + artifactName: 'unknown', + address: '0x058c345D3240001088b6280e008F9e78b3B2112d', + category: AddressCategory.External + }, + + curveLPTokenOracle: { + artifactName: 'unknown', + address: '0xa9f3faac3b8eDF7b3DCcFDBBf25033D6F5fc02F3', + category: AddressCategory.External + }, + + gUniFuseOracle: { + artifactName: 'unknown', + address: '0xEa3633b38C747ceA231aDB74b511DC2eD3992B43', + category: AddressCategory.External + }, + + rariPool8Lusd: { + artifactName: 'CErc20Delegator', + address: '0x647A36d421183a0a9Fa62717a64B664a24E469C7', + category: AddressCategory.External + }, + + rariPool8Dai: { + artifactName: 'CErc20Delegator', + address: '0x7e9cE3CAa9910cc048590801e64174957Ed41d43', + category: AddressCategory.External + }, + + rariPool8DaiIrm: { + artifactName: 'unknown', + address: '0xede47399e2aa8f076d40dc52896331cba8bd40f7', + category: AddressCategory.External + }, + + rariPool8Eth: { + artifactName: 'CErc20Delegator', + address: '0xbB025D470162CC5eA24daF7d4566064EE7f5F111', + category: AddressCategory.External + }, + + rariPool8EthIrm: { + artifactName: 'unknown', + address: '0xbab47e4b692195bf064923178a90ef999a15f819', + category: AddressCategory.External + }, + + rariPool8Fei: { + artifactName: 'CErc20Delegator', + address: '0xd8553552f8868C1Ef160eEdf031cF0BCf9686945', + category: AddressCategory.External + }, + + rariPool8FeiIrm: { + artifactName: 'unknown', + address: '0x8f47be5692180079931e2f983db6996647aba0a5', + category: AddressCategory.External + }, + + rariPool8Tribe: { + artifactName: 'CErc20Delegator', + address: '0xFd3300A9a74b3250F1b2AbC12B47611171910b07', + category: AddressCategory.External + }, + + rariPool8TribeIrm: { + artifactName: 'unknown', + address: '0x075538650a9c69ac8019507a7dd1bd879b12c1d7', + category: AddressCategory.External + }, + + rariPool8CTokenImpl: { + artifactName: 'unknown', + address: '0x67Db14E73C2Dce786B5bbBfa4D010dEab4BBFCF9', + category: AddressCategory.External + }, + + rariPool8Fei3Crv: { + artifactName: 'CErc20Delegator', + address: '0xBFB6f7532d2DB0fE4D83aBb001c5C2B0842AF4dB', + category: AddressCategory.External + }, + + rariPool8FeiD3: { + artifactName: 'CErc20Delegator', + address: '0x5cA8Ffe4DAD9452ED880FA429DD0A08574225936', + category: AddressCategory.External + }, + + rariPool146Comptroller: { + artifactName: 'Unitroller', + address: '0x88F7c23EA6C4C404dA463Bc9aE03b012B32DEf9e', + category: AddressCategory.External + }, + + rariPool146FuseAdmin: { + artifactName: 'FuseAdmin', + address: '0x6d64D080345C446dA31b8D3855bA6d9C0fC875D2', + category: AddressCategory.External + }, + + rariPool146Eth: { + artifactName: 'unknown', + address: '0xfbD8Aaf46Ab3C2732FA930e5B343cd67cEA5054C', + category: AddressCategory.External + }, + + rariTimelockFeiOldLens: { + artifactName: 'ERC20PCVDepositWrapper', + address: '0x614D46B7eB2AC1a359b8835D64954F3Ee4E6F676', + category: AddressCategory.Deprecated + }, + + fuseAdmin: { + artifactName: 'FuseAdmin', + address: '0x761dD1Ae03D95BdABeC3C228532Dcdab4F2c7adD', + category: AddressCategory.Deprecated + }, + + fuseGuardian: { + artifactName: 'FuseGuardian', + address: '0xc0c59A2d3F278445f27ed4a00E2727D6c677c43F', + category: AddressCategory.Deprecated + }, + + proxyAdmin: { + artifactName: 'ProxyAdmin', + address: '0xf8c2b645988b7658E7748BA637fE25bdD46A704A', + category: AddressCategory.Deprecated + }, + + rariTimelock: { + artifactName: 'Timelock', + address: '0x8ace03Fc45139fDDba944c6A4082b604041d19FC', + category: AddressCategory.Deprecated + }, + + tribeRariDAO: { + artifactName: 'FeiDAO', + address: '0x637deEED4e4deb1D222650bD4B64192abf002c00', + category: AddressCategory.Deprecated + }, + + rariGovernanceProxyAdmin: { + artifactName: 'ProxyAdmin', + address: '0x1c9aA54a013962C2444ECae06902F31D532c6AD3', + category: AddressCategory.Deprecated + }, + + tribeMinter: { + artifactName: 'TribeMinter', + address: '0xFC3532b443383d9022b1B2c6FD5Fd0895943360A', + category: AddressCategory.Deprecated + }, + + collateralizationOracle: { + artifactName: 'CollateralizationOracle', + address: '0xFF6f59333cfD8f4Ebc14aD0a0E181a83e655d257', + category: AddressCategory.Deprecated + }, + guardianMultisig: { + artifactName: 'unknown', + address: '0xB8f482539F2d3Ae2C9ea6076894df36D1f632775', + category: AddressCategory.Deprecated + }, + feiDAO: { + artifactName: 'FeiDAO', + address: '0x0BEF27FEB58e857046d630B2c03dFb7bae567494', + category: AddressCategory.Deprecated + }, + feiDAOTimelock: { + artifactName: 'FeiDAOTimelock', + address: '0xd51dbA7a94e1adEa403553A8235C302cEbF41a3c', + category: AddressCategory.Deprecated + }, + pcvGuardian: { artifactName: 'PCVGuardian', address: '0x02435948F84d7465FB71dE45ABa6098Fc6eC2993', @@ -2728,11 +2735,6 @@ export const MainnetContractsConfig = { address: '0x4bFa2625D50b68D622D1e71c82ba6Db99BA0d17F', category: AddressCategory.Deprecated }, - feiLabsVestingTimelock: { - artifactName: 'TimelockedDelegator', - address: '0x38afbf8128cc54323e216acde9516d281c4f1e5f', - category: AddressCategory.Deprecated - }, pegExchanger: { artifactName: 'PegExchanger', diff --git a/protocol-configuration/optimisticGovernance.ts b/protocol-configuration/optimisticGovernance.ts index b56e57108..4e8214932 100644 --- a/protocol-configuration/optimisticGovernance.ts +++ b/protocol-configuration/optimisticGovernance.ts @@ -1,3 +1,4 @@ +// Deprecated: Optimistic governance is no longer live and in use export const tribalCouncilMembers = [ '0xc8eefb8b3d50ca87Da7F99a661720148acf97EfA', '0x72b7448f470D07222Dbf038407cD69CC380683F3', diff --git a/protocol-configuration/permissions.ts b/protocol-configuration/permissions.ts index 934e2f7cb..7256ca88b 100644 --- a/protocol-configuration/permissions.ts +++ b/protocol-configuration/permissions.ts @@ -2,9 +2,9 @@ export const PermissionsConfig = { MINTER_ROLE: ['simpleFeiDaiPSM'], - GOVERN_ROLE: ['core', 'feiDAOTimelock'], - PCV_CONTROLLER_ROLE: ['feiDAOTimelock', 'vebalOtcHelper'], - GUARDIAN_ROLE: ['guardianMultisig'], + GOVERN_ROLE: [], + PCV_CONTROLLER_ROLE: ['vebalOtcHelper'], + GUARDIAN_ROLE: [], METAGOVERNANCE_VOTE_ADMIN: ['vebalOtcHelper'], METAGOVERNANCE_TOKEN_STAKING: ['vebalOtcHelper'], METAGOVERNANCE_GAUGE_ADMIN: ['vebalOtcHelper'], diff --git a/protocol-configuration/proposalsConfig.ts b/protocol-configuration/proposalsConfig.ts index 83d68c1e9..04aeff61d 100644 --- a/protocol-configuration/proposalsConfig.ts +++ b/protocol-configuration/proposalsConfig.ts @@ -1,17 +1,18 @@ import { ProposalCategory, TemplatedProposalsConfigMap } from '@custom-types/types'; import fip_x from '@proposals/description/fip_x'; +import tip_123 from '@proposals/description/tip_123'; export const ProposalsConfig: TemplatedProposalsConfigMap = { - // fip_x: { - // deploy: false, // deploy flag for whether to run deploy action during e2e tests or use mainnet state - // totalValue: 0, // amount of ETH to send to DAO execution - // proposal: fip_x, // full proposal file, imported from '@proposals/description/fip_xx.ts' - // proposalId: '', - // affectedContractSignoff: [], - // deprecatedContractSignoff: [], - // category: ProposalCategory.DAO - // } + tip_123: { + deploy: false, // deploy flag for whether to run deploy action during e2e tests or use mainnet state + totalValue: 0, // amount of ETH to send to DAO execution + proposal: tip_123, // full proposal file, imported from '@proposals/description/fip_xx.ts' + proposalId: '', + affectedContractSignoff: [], + deprecatedContractSignoff: [], + category: ProposalCategory.DAO + } }; export default ProposalsConfig; diff --git a/protocol-configuration/safeAddresses.ts b/protocol-configuration/safeAddresses.ts index e19e840b6..f8c98ad12 100644 --- a/protocol-configuration/safeAddresses.ts +++ b/protocol-configuration/safeAddresses.ts @@ -1,3 +1,4 @@ // This config lists all of the addresses that should be "safe" in the PCVGuardian. +// Deprecated: SafeAddresses are deprecated as the PCVGuardian no longer has any roles or permissions export const SafeAddressesConfig = ['feiDAOTimelock', 'simpleFeiDaiPSM']; diff --git a/scripts/utils/sudo.ts b/scripts/utils/sudo.ts index 6b9bc35fc..5f8850194 100644 --- a/scripts/utils/sudo.ts +++ b/scripts/utils/sudo.ts @@ -9,8 +9,6 @@ dotenv.config(); // Grants Governor, Minter, Burner, and PCVController access to accounts[0] // Also mints a large amount of FEI to accounts[0] export async function sudo(contracts: NamedContracts, logging = false): Promise { - const core = contracts.core; - const fei = contracts.fei; const timelock = contracts.feiDAOTimelock; // Impersonate the Timelock which has Governor access on-chain @@ -19,8 +17,6 @@ export async function sudo(contracts: NamedContracts, logging = false): Promise< params: [timelock.address] }); - const accounts = await ethers.getSigners(); - // Force ETH to the Timelock to send txs on its behalf logging ? console.log('Forcing ETH to timelock') : undefined; await forceEth(timelock.address); @@ -29,19 +25,4 @@ export async function sudo(contracts: NamedContracts, logging = false): Promise< method: 'hardhat_impersonateAccount', params: [timelock.address] }); - - const timelockSigner = await ethers.getSigner(timelock.address); - - // Use timelock to grant access - logging ? console.log('Granting roles to accounts[0]') : undefined; - await core.connect(timelockSigner).grantGovernor(accounts[0].address); - - await hre.network.provider.request({ - method: 'hardhat_stopImpersonatingAccount', - params: [timelock.address] - }); - - await core.grantPCVController(accounts[0].address); - await core.grantMinter(accounts[0].address); - await core.grantBurner(accounts[0].address); } diff --git a/test/integration/tests/balancerGaugeStaker.ts b/test/integration/tests/balancerGaugeStaker.ts index 9c10f329b..4339fe79d 100644 --- a/test/integration/tests/balancerGaugeStaker.ts +++ b/test/integration/tests/balancerGaugeStaker.ts @@ -37,7 +37,6 @@ describe('e2e-metagov', function () { describe('BalancerGaugeStaker.sol', function () { let staker: BalancerGaugeStakerV2; let veBalOtcHelperContract: SignerWithAddress; - let daoSigner: SignerWithAddress; let randomSigner: SignerWithAddress; before(async function () { @@ -59,10 +58,10 @@ describe('e2e-metagov', function () { await forceEth(randomSigner.address); // seed the staker with some LP tokens - const lpTokenHolder = '0xf4adc8369e83d6a599e51438d44b5e53a412f807'; + const lpTokenHolder = '0x4f9463405f5bc7b4c1304222c1df76efbd81a407'; const lpTokenSigner = await getImpersonatedSigner(lpTokenHolder); await forceEth(lpTokenHolder); - await contracts.bpt30Fei70Weth.connect(lpTokenSigner).transfer(staker.address, `100${e18}`); + await contracts.bpt30Fei70Weth.connect(lpTokenSigner).transfer(staker.address, `40${e18}`); // also airdrop some BAL so that balance is not zero const balTokenHolder = '0xBA12222222228d8Ba445958a75a0704d566BF2C8'; @@ -72,10 +71,6 @@ describe('e2e-metagov', function () { veBalOtcHelperContract = await getImpersonatedSigner(contracts.vebalOtcHelper.address); await forceEth(contracts.vebalOtcHelper.address); - - // Initialise dao signer - daoSigner = await getImpersonatedSigner(contracts.feiDAOTimelock.address); - await forceEth(contracts.feiDAOTimelock.address); }); it('init', async function () { @@ -107,12 +102,6 @@ describe('e2e-metagov', function () { ); }); - it('should revert if contract is paused', async function () { - await staker.connect(daoSigner).pause(); - await expectRevert(staker.withdraw(veBalOtcHelperContract.address, '10'), 'Pausable: paused'); - await staker.connect(daoSigner).unpause(); - }); - it('should work if user has PCV_CONTROLLER_ROLE role', async function () { const balanceBefore = await contracts.bal.balanceOf(veBalOtcHelperContract.address); await staker.connect(veBalOtcHelperContract).withdraw(veBalOtcHelperContract.address, '10'); @@ -152,12 +141,6 @@ describe('e2e-metagov', function () { ); }); - it('should revert if contract is paused', async function () { - await staker.connect(daoSigner).pause(); - await expectRevert(staker.withdraw(veBalOtcHelperContract.address, '10'), 'Pausable: paused'); - await staker.connect(daoSigner).unpause(); - }); - it('should work if user has PCV_CONTROLLER_ROLE role', async function () { const balanceBefore = await contracts.bal.balanceOf(veBalOtcHelperContract.address); await expectEvent( diff --git a/test/integration/tests/dao.ts b/test/integration/tests/dao.ts index 20b831ba3..22ffec7c9 100644 --- a/test/integration/tests/dao.ts +++ b/test/integration/tests/dao.ts @@ -1,17 +1,14 @@ import { Core } from '@custom-types/contracts'; -import { ContractAccessRights, NamedAddresses, NamedContracts } from '@custom-types/types'; +import { ContractAccessRights, NamedContracts } from '@custom-types/types'; import { ProposalsConfig } from '@protocol/proposalsConfig'; -import { getImpersonatedSigner, increaseTime, latestTime, time } from '@test/helpers'; import { TestEndtoEndCoordinator } from '@test/integration/setup'; -import { forceEth } from '@test/integration/setup/utils'; import chai, { expect } from 'chai'; import CBN from 'chai-bn'; import { solidity } from 'ethereum-waffle'; -import hre, { ethers } from 'hardhat'; +import { ethers } from 'hardhat'; describe('e2e-dao', function () { let contracts: NamedContracts; - let contractAddresses: NamedAddresses; let deployAddress: string; let e2eCoord: TestEndtoEndCoordinator; let doLogging: boolean; @@ -38,92 +35,11 @@ describe('e2e-dao', function () { e2eCoord = new TestEndtoEndCoordinator(config, ProposalsConfig); doLogging && console.log(`Loading environment...`); - ({ contracts, contractAddresses } = await e2eCoord.loadEnvironment()); + ({ contracts } = await e2eCoord.loadEnvironment()); doLogging && console.log(`Environment loaded.`); }); - describe('FeiDAOTimelock', async function () { - it('veto succeeds', async function () { - const { feiDAO, feiDAOTimelock } = contracts; - - const eta = (await latestTime()) + 100000; - const timelockSigner = await getImpersonatedSigner(feiDAO.address); - await forceEth(feiDAO.address); - const q = await feiDAOTimelock.connect(timelockSigner).queueTransaction(deployAddress, 100, '', '0x', eta); - - const txHash = (await q.wait()).events[0].args[0]; - expect(await feiDAOTimelock.queuedTransactions(txHash)).to.be.equal(true); - - await feiDAOTimelock - .connect(await getImpersonatedSigner(deployAddress)) - .vetoTransactions([deployAddress], [100], [''], ['0x'], [eta]); - expect(await feiDAOTimelock.queuedTransactions(txHash)).to.be.equal(false); - }); - }); - - describe('Fei DAO', function () { - it('proposal succeeds', async function () { - const feiDAO = contracts.feiDAO; - - const targets = [feiDAO.address]; - const values = [0]; - const calldatas = [ - '0x70b0f660000000000000000000000000000000000000000000000000000000000000000a' // set voting delay 10 - ]; - const description: any[] = []; - - const treasurySigner = await getImpersonatedSigner(contractAddresses.core); - await forceEth(contractAddresses.core); - await contracts.tribe.connect(treasurySigner).delegate(contractAddresses.guardianMultisig); - const signer = await getImpersonatedSigner(contractAddresses.guardianMultisig); - - // Propose - // note ethers.js requires using this notation when two overloaded methods exist) - // https://docs.ethers.io/v5/migration/web3/#migration-from-web3-js--contracts--overloaded-functions - await feiDAO - .connect(signer) - ['propose(address[],uint256[],bytes[],string)'](targets, values, calldatas, description); - - const pid = await feiDAO.hashProposal(targets, values, calldatas, ethers.utils.keccak256(description)); - - await time.advanceBlock(); - - // vote - await feiDAO.connect(signer).castVote(pid, 1); - - // advance to end of voting period - const endBlock = (await feiDAO.proposals(pid)).endBlock; - await time.advanceBlockTo(endBlock.toNumber()); - - // queue - await feiDAO['queue(address[],uint256[],bytes[],bytes32)']( - targets, - values, - calldatas, - ethers.utils.keccak256(description) - ); - - await time.increase('1000000'); - - // execute - await feiDAO['execute(address[],uint256[],bytes[],bytes32)']( - targets, - values, - calldatas, - ethers.utils.keccak256(description) - ); - - expect((await feiDAO.votingDelay()).toString()).to.be.equal('10'); - }); - }); - describe('Access control', async () => { - before(async () => { - // Revoke deploy address permissions, so that does not erroneously - // contribute to num governor roles etc - await e2eCoord.revokeDeployAddressPermission(); - }); - it('should have granted correct role cardinality', async function () { const core = contracts.core; const accessRights = e2eCoord.getAccessControlMapping(); @@ -136,7 +52,7 @@ describe('e2e-dao', function () { const numRoles = await core.getRoleMemberCount(id); doLogging && console.log(`Role count for ${element}: ${numRoles}`); // in e2e setup, deployer address has minter role - expect(numRoles.toNumber() - (element == 'MINTER_ROLE' ? 1 : 0)).to.be.equal( + expect(numRoles.toNumber()).to.be.equal( accessRights[element as keyof ContractAccessRights].length, 'role ' + element ); @@ -168,7 +84,7 @@ describe('e2e-dao', function () { doLogging && console.log(`Testing tribe minter address...`); const tribe = contracts.tribe; const tribeMinter = await tribe.minter(); - expect(tribeMinter).to.equal(contractAddresses.tribeMinter); + expect(tribeMinter).to.equal(ethers.constants.AddressZero); }); }); }); diff --git a/test/integration/tests/simpleFeiDaiPSM.ts b/test/integration/tests/simpleFeiDaiPSM.ts index f695b97e8..dbfc3e71c 100644 --- a/test/integration/tests/simpleFeiDaiPSM.ts +++ b/test/integration/tests/simpleFeiDaiPSM.ts @@ -57,9 +57,6 @@ describe('e2e-peg-stability-module', function () { for (const address of impersonatedAddresses) { impersonatedSigners[address] = await getImpersonatedSigner(address); } - - const daoTimelockSigner = await getImpersonatedSigner(contracts.feiDAOTimelock.address); - await contracts.core.connect(daoTimelockSigner).grantPCVController(contracts.feiDAOTimelock.address); }); describe('simpleFeiDaiPSM', async () => { diff --git a/test/integration/tests/tribeRedeemer.ts b/test/integration/tests/tribeRedeemer.ts index 739e6de87..cd9788aa7 100644 --- a/test/integration/tests/tribeRedeemer.ts +++ b/test/integration/tests/tribeRedeemer.ts @@ -69,8 +69,8 @@ describe('e2e-tribe-redeemer', function () { expect(amountsOut[1]).to.be.at.most(ethers.constants.WeiPerEther.mul(25)); expect(amountsOut[2]).to.be.at.least(ethers.constants.WeiPerEther.mul(330)); // 333.72 FOX expect(amountsOut[2]).to.be.at.most(ethers.constants.WeiPerEther.mul(335)); - expect(amountsOut[3]).to.be.at.least(ethers.constants.WeiPerEther.mul(700)); // 701.525 DAI - expect(amountsOut[3]).to.be.at.most(ethers.constants.WeiPerEther.mul(705)); + expect(amountsOut[3]).to.be.at.least(ethers.constants.WeiPerEther.mul(712)); // 714.34 DAI + expect(amountsOut[3]).to.be.at.most(ethers.constants.WeiPerEther.mul(717)); }); it('redeem() 1,000,000 TRIBE, twice', async () => { @@ -119,8 +119,8 @@ describe('e2e-tribe-redeemer', function () { const daiPerRedeem = daiBalance1.sub(daiBalance0); expect(stethPerRedeem).to.be.at.least(ethers.constants.WeiPerEther.mul(109)); expect(stethPerRedeem).to.be.at.most(ethers.constants.WeiPerEther.mul(112)); - expect(daiPerRedeem).to.be.at.least(ethers.constants.WeiPerEther.mul(70000)); - expect(daiPerRedeem).to.be.at.most(ethers.constants.WeiPerEther.mul(70500)); + expect(daiPerRedeem).to.be.at.least(ethers.constants.WeiPerEther.mul(71200)); + expect(daiPerRedeem).to.be.at.most(ethers.constants.WeiPerEther.mul(71700)); }); it('small redeemooor', async () => { @@ -147,8 +147,8 @@ describe('e2e-tribe-redeemer', function () { const daiReceived = daiBalance1.sub(daiBalance0); expect(stethReceived).to.be.at.least('109000000'); // >= 0.000000000109 stETH expect(stethReceived).to.be.at.most('112000000'); // <= 0.000000000112 stETH - expect(daiReceived).to.be.at.least('70000000000'); // >= 0.0000000700 DAI - expect(daiReceived).to.be.at.most('71000000000'); // <>>= 0.0.0000000710 DAI + expect(daiReceived).to.be.at.least('71200000000'); // >= 0.0000000712 DAI + expect(daiReceived).to.be.at.most('71700000000'); // <>>= 0.0.0000000717 DAI }); it('dust redeemooor', async () => { @@ -200,7 +200,7 @@ describe('e2e-tribe-redeemer', function () { const expectedAmounts = { redeemedAmount: ethers.constants.WeiPerEther.mul(10_000), steth: ethers.BigNumber.from('1096463758637073656'), // 1.0964 stETH - dai: ethers.BigNumber.from('701525436619890200000') // 701.525 DAI + dai: ethers.BigNumber.from('714335537896449685994') // 713.34 DAI }; for (let i = 0; i < 10; i++) { const multiplier = Math.floor(Math.random() * 100) + 1; @@ -251,8 +251,8 @@ describe('e2e-tribe-redeemer', function () { const daiReceived = daiBalance1.sub(daiBalance0); expect(stethReceived).to.be.at.least(ethers.constants.WeiPerEther.mul(109).div(100)); // 1.0964 stETH expect(stethReceived).to.be.at.most(ethers.constants.WeiPerEther.mul(112).div(100)); - expect(daiReceived).to.be.at.least(ethers.constants.WeiPerEther.mul(700)); // 701.525 DAI - expect(daiReceived).to.be.at.most(ethers.constants.WeiPerEther.mul(705)); + expect(daiReceived).to.be.at.least(ethers.constants.WeiPerEther.mul(712)); // 714.34 DAI + expect(daiReceived).to.be.at.most(ethers.constants.WeiPerEther.mul(717)); // balance after all redeems expect(await contracts.steth.balanceOf(contracts.tribeRedeemer.address)).to.be.at.most('1'); diff --git a/test/integration/tests/veBalHelper_boost.ts b/test/integration/tests/veBalHelper_boost.ts index 1d08f1b17..fc7d025f9 100644 --- a/test/integration/tests/veBalHelper_boost.ts +++ b/test/integration/tests/veBalHelper_boost.ts @@ -73,7 +73,7 @@ describe('e2e-veBalHelper-boost-management', function () { '1672272000', // uint256 _expire_time = December 29 2022 '0' // uint256 _id ); - const expectedMinBoost = '65000000000000000000000'; // should be 77.5k with 18 decimals as of 14/09/2022 + const expectedMinBoost = '60000000000000000000000'; // should be 77.5k with 18 decimals as of 14/09/2022 expect( await contracts.balancerVotingEscrowDelegation.delegated_boost(contracts.veBalDelegatorPCVDeposit.address) ).to.be.at.least(expectedMinBoost); diff --git a/test/integration/tests/veBalHelper_gauge.ts b/test/integration/tests/veBalHelper_gauge.ts index 1ce5ecd03..ec88236e4 100644 --- a/test/integration/tests/veBalHelper_gauge.ts +++ b/test/integration/tests/veBalHelper_gauge.ts @@ -28,7 +28,7 @@ describe('e2e-veBalHelper-gauge-management', function () { let otcBuyerSigner: SignerWithAddress; let gaugeTokenHolderSigner: SignerWithAddress; - const balFeiWethGaugeTokenHolder = '0xf4adc8369e83d6a599e51438d44b5e53a412f807'; + const balFeiWethGaugeTokenHolder = '0x4f9463405f5bc7b4c1304222c1df76efbd81a407'; before(async function () { deployAddress = (await ethers.getSigners())[0].address; diff --git a/test/integration/tests/veBalHelper_voteLock.ts b/test/integration/tests/veBalHelper_voteLock.ts index fa3f179f5..f7315cc48 100644 --- a/test/integration/tests/veBalHelper_voteLock.ts +++ b/test/integration/tests/veBalHelper_voteLock.ts @@ -59,6 +59,7 @@ describe('e2e-veBalHelper-vote-lock', function () { } otcBuyerAddress = contractAddresses.aaveCompaniesMultisig; + await forceEth(otcBuyerAddress); otcBuyerSigner = await getImpersonatedSigner(otcBuyerAddress); await forceEth(otcBuyerAddress);