From 6b0cdaf26a0be563bd537ce8e84fc2e314a0de94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8r=E2=88=82=C2=A1?= Date: Thu, 28 Nov 2024 13:47:14 +0700 Subject: [PATCH 1/4] Turning the timelock value into a governance setting --- .env.example | 1 + script/Deploy.s.sol | 18 +-- src/OptimisticTokenVotingPlugin.sol | 13 +- src/factory/TaikoDaoFactory.sol | 10 +- test/OptimisticTokenVotingPlugin.t.sol | 137 +++++++++++++++----- test/OptimisticTokenVotingPluginSetup.t.sol | 21 ++- test/helpers/DaoBuilder.sol | 17 ++- test/integration/TaikoDaoFactory.t.sol | 55 ++++---- 8 files changed, 186 insertions(+), 86 deletions(-) diff --git a/.env.example b/.env.example index eb35073..a242adc 100644 --- a/.env.example +++ b/.env.example @@ -22,6 +22,7 @@ MULTISIG_MEMBERS_JSON_FILE_NAME="/script/multisig-members.json" # GOVERNANCE PARAMETERS MIN_VETO_RATIO="300000" # 30% (base 1_000_000) +TIME_LOCK_PERIOD="604800" # in seconds (7 days) L2_INACTIVITY_PERIOD="600" # in seconds (10 minutes) L2_AGGREGATION_GRACE_PERIOD="172800" # in seconds (2 days) SKIP_L2=true # Determines whether vote aggregation from the L2 will be disabled diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index 1ec9cff..7118942 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -74,12 +74,13 @@ contract Deploy is Script { tokenAddress: IVotesUpgradeable(vm.envAddress("TOKEN_ADDRESS")), taikoL1ContractAddress: vm.envAddress("TAIKO_L1_ADDRESS"), taikoBridgeAddress: vm.envAddress("TAIKO_BRIDGE_ADDRESS"), - l2InactivityPeriod: uint64(vm.envUint("L2_INACTIVITY_PERIOD")), - l2AggregationGracePeriod: uint64(vm.envUint("L2_AGGREGATION_GRACE_PERIOD")), + timelockPeriod: uint32(vm.envUint("TIME_LOCK_PERIOD")), + l2InactivityPeriod: uint32(vm.envUint("L2_INACTIVITY_PERIOD")), + l2AggregationGracePeriod: uint32(vm.envUint("L2_AGGREGATION_GRACE_PERIOD")), skipL2: bool(vm.envBool("SKIP_L2")), // Voting settings minVetoRatio: uint32(vm.envUint("MIN_VETO_RATIO")), - minStdProposalDuration: uint64(vm.envUint("MIN_STD_PROPOSAL_DURATION")), + minStdProposalDuration: uint32(vm.envUint("MIN_STD_PROPOSAL_DURATION")), minStdApprovals: uint16(vm.envUint("MIN_STD_APPROVALS")), minEmergencyApprovals: uint16(vm.envUint("MIN_EMERGENCY_APPROVALS")), // OSx contracts @@ -92,7 +93,7 @@ contract Deploy is Script { optimisticTokenVotingPluginSetup: OptimisticTokenVotingPluginSetup(optimisticTokenVotingPluginSetup), // Multisig members multisigMembers: readMultisigMembers(), - multisigExpirationPeriod: uint64(vm.envUint("MULTISIG_PROPOSAL_EXPIRATION_PERIOD")), + multisigExpirationPeriod: uint32(vm.envUint("MULTISIG_PROPOSAL_EXPIRATION_PERIOD")), // ENS stdMultisigEnsDomain: vm.envString("STD_MULTISIG_ENS_DOMAIN"), emergencyMultisigEnsDomain: vm.envString("EMERGENCY_MULTISIG_ENS_DOMAIN"), @@ -112,12 +113,13 @@ contract Deploy is Script { tokenAddress: IVotesUpgradeable(votingToken), taikoL1ContractAddress: address(new TaikoL1Mock()), taikoBridgeAddress: taikoBridgeAddress, - l2InactivityPeriod: uint64(vm.envUint("L2_INACTIVITY_PERIOD")), - l2AggregationGracePeriod: uint64(vm.envUint("L2_AGGREGATION_GRACE_PERIOD")), + timelockPeriod: uint32(vm.envUint("TIME_LOCK_PERIOD")), + l2InactivityPeriod: uint32(vm.envUint("L2_INACTIVITY_PERIOD")), + l2AggregationGracePeriod: uint32(vm.envUint("L2_AGGREGATION_GRACE_PERIOD")), skipL2: bool(vm.envBool("SKIP_L2")), // Voting settings minVetoRatio: uint32(vm.envUint("MIN_VETO_RATIO")), - minStdProposalDuration: uint64(vm.envUint("MIN_STD_PROPOSAL_DURATION")), + minStdProposalDuration: uint32(vm.envUint("MIN_STD_PROPOSAL_DURATION")), minStdApprovals: uint16(vm.envUint("MIN_STD_APPROVALS")), minEmergencyApprovals: uint16(vm.envUint("MIN_EMERGENCY_APPROVALS")), // OSx contracts @@ -130,7 +132,7 @@ contract Deploy is Script { optimisticTokenVotingPluginSetup: OptimisticTokenVotingPluginSetup(optimisticTokenVotingPluginSetup), // Multisig members multisigMembers: multisigMembers, - multisigExpirationPeriod: uint64(vm.envUint("MULTISIG_PROPOSAL_EXPIRATION_PERIOD")), + multisigExpirationPeriod: uint32(vm.envUint("MULTISIG_PROPOSAL_EXPIRATION_PERIOD")), // ENS stdMultisigEnsDomain: vm.envString("STD_MULTISIG_ENS_DOMAIN"), emergencyMultisigEnsDomain: vm.envString("EMERGENCY_MULTISIG_ENS_DOMAIN"), diff --git a/src/OptimisticTokenVotingPlugin.sol b/src/OptimisticTokenVotingPlugin.sol index 2e91116..2ecf6e8 100644 --- a/src/OptimisticTokenVotingPlugin.sol +++ b/src/OptimisticTokenVotingPlugin.sol @@ -34,14 +34,16 @@ contract OptimisticTokenVotingPlugin is /// @notice A container for the optimistic majority settings that will be applied as parameters on proposal creation. /// @param minVetoRatio The support threshold value. Its value has to be in the interval [0, 10^6] defined by `RATIO_BASE = 10**6`. /// @param minDuration The minimum duration of the proposal vote in seconds. + /// @param timelockPeriod The time in seconds between a proposal passing and execution being unlocked /// @param l2InactivityPeriod The age in seconds of the latest block, after which the L2 is considered unavailable. /// @param l2AggregationGracePeriod The amount of extra seconds to allow for L2 veto bridging after `vetoEndDate` is reached. /// @param skipL2 Defines wether the plugin should ignore the voting power bridged to the L2, in terms of the token supply and L2 votes accepted. NOTE: Ongoing proposals will keep the value of the setting at the time of creation. struct OptimisticGovernanceSettings { uint32 minVetoRatio; - uint64 minDuration; - uint64 l2InactivityPeriod; - uint64 l2AggregationGracePeriod; + uint32 minDuration; + uint32 timelockPeriod; + uint32 l2InactivityPeriod; + uint32 l2AggregationGracePeriod; bool skipL2; } @@ -84,9 +86,6 @@ contract OptimisticTokenVotingPlugin is bytes32 public constant UPDATE_OPTIMISTIC_GOVERNANCE_SETTINGS_PERMISSION_ID = keccak256("UPDATE_OPTIMISTIC_GOVERNANCE_SETTINGS_PERMISSION"); - /// @notice The time gap between a proposal passing and execution being unlocked - uint64 public constant EXIT_WINDOW = 7 days; - /// @notice An [OpenZeppelin `Votes`](https://docs.openzeppelin.com/contracts/4.x/api/governance#Votes) compatible contract referencing the token being used for voting. IVotesUpgradeable public votingToken; @@ -580,7 +579,7 @@ contract OptimisticTokenVotingPlugin is /// @param proposal_ The proposal struct. /// @return True if the proposal cannot be executed because the exit window hasn't elapsed yet function _proposalInExitWindow(Proposal storage proposal_) internal view virtual returns (bool) { - uint64 exitWindowTimestamp = proposal_.parameters.vetoEndDate + EXIT_WINDOW; + uint64 exitWindowTimestamp = proposal_.parameters.vetoEndDate + governanceSettings.timelockPeriod; if (!proposal_.parameters.unavailableL2) { exitWindowTimestamp += governanceSettings.l2AggregationGracePeriod; diff --git a/src/factory/TaikoDaoFactory.sol b/src/factory/TaikoDaoFactory.sol index b5733fa..c47e369 100644 --- a/src/factory/TaikoDaoFactory.sol +++ b/src/factory/TaikoDaoFactory.sol @@ -51,12 +51,13 @@ contract TaikoDaoFactory { IVotesUpgradeable tokenAddress; address taikoL1ContractAddress; address taikoBridgeAddress; - uint64 l2InactivityPeriod; - uint64 l2AggregationGracePeriod; + uint32 timelockPeriod; + uint32 l2InactivityPeriod; + uint32 l2AggregationGracePeriod; bool skipL2; // Voting settings uint32 minVetoRatio; - uint64 minStdProposalDuration; + uint32 minStdProposalDuration; uint16 minStdApprovals; uint16 minEmergencyApprovals; // OSx contracts @@ -69,7 +70,7 @@ contract TaikoDaoFactory { OptimisticTokenVotingPluginSetup optimisticTokenVotingPluginSetup; // Multisig address[] multisigMembers; - uint64 multisigExpirationPeriod; + uint32 multisigExpirationPeriod; // ENS string stdMultisigEnsDomain; string emergencyMultisigEnsDomain; @@ -291,6 +292,7 @@ contract TaikoDaoFactory { .OptimisticGovernanceSettings( settings.minVetoRatio, 0, // minDuration (the condition contract will enforce it) + settings.timelockPeriod, settings.l2InactivityPeriod, settings.l2AggregationGracePeriod, settings.skipL2 diff --git a/test/OptimisticTokenVotingPlugin.t.sol b/test/OptimisticTokenVotingPlugin.t.sol index a01beb0..721c535 100644 --- a/test/OptimisticTokenVotingPlugin.t.sol +++ b/test/OptimisticTokenVotingPlugin.t.sol @@ -62,6 +62,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 10), minDuration: 10 days, + timelockPeriod: 7 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -77,6 +78,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 10), minDuration: 7 days, + timelockPeriod: 12 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -91,14 +93,16 @@ contract OptimisticTokenVotingPluginTest is AragonTest { ); ( uint32 minVetoRatio, - uint64 minDuration, - uint64 l2InactivityPeriod, - uint64 l2AggregationGracePeriod, + uint32 minDuration, + uint32 timelockPeriod, + uint32 l2InactivityPeriod, + uint32 l2AggregationGracePeriod, bool skipL2 ) = optimisticPlugin.governanceSettings(); assertEq(optimisticPlugin.minVetoRatio(), uint32(RATIO_BASE / 10), "Incorrect minVetoRatio()"); assertEq(minVetoRatio, uint32(RATIO_BASE / 10), "Incorrect minVetoRatio"); assertEq(minDuration, 7 days, "Incorrect minDuration"); + assertEq(timelockPeriod, 12 days, "Incorrect timelockPeriod"); assertEq(l2InactivityPeriod, 10 minutes, "Incorrect l2InactivityPeriod"); assertEq(l2AggregationGracePeriod, 2 days, "Incorrect l2AggregationGracePeriod"); assertEq(skipL2, false, "Incorrect skipL2"); @@ -118,11 +122,12 @@ contract OptimisticTokenVotingPluginTest is AragonTest { ) ) ); - (minVetoRatio, minDuration, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = + (minVetoRatio, minDuration, timelockPeriod, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = optimisticPlugin.governanceSettings(); assertEq(optimisticPlugin.minVetoRatio(), uint32(RATIO_BASE / 5), "Incorrect minVetoRatio()"); assertEq(minVetoRatio, uint32(RATIO_BASE / 5), "Incorrect minVetoRatio"); assertEq(minDuration, 7 days, "Incorrect minDuration"); + assertEq(timelockPeriod, 12 days, "Incorrect timelockPeriod"); assertEq(l2InactivityPeriod, 10 minutes, "Incorrect l2InactivityPeriod"); assertEq(l2AggregationGracePeriod, 2 days, "Incorrect l2AggregationGracePeriod"); assertEq(skipL2, false, "Incorrect skipL2"); @@ -143,11 +148,38 @@ contract OptimisticTokenVotingPluginTest is AragonTest { ) ); - (minVetoRatio, minDuration, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = + (minVetoRatio, minDuration, timelockPeriod, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = optimisticPlugin.governanceSettings(); assertEq(optimisticPlugin.minVetoRatio(), uint32(RATIO_BASE / 5), "Incorrect minVetoRatio()"); assertEq(minVetoRatio, uint32(RATIO_BASE / 5), "Incorrect minVetoRatio"); assertEq(minDuration, 25 days, "Incorrect minDuration"); + assertEq(timelockPeriod, 12 days, "Incorrect timelockPeriod"); + assertEq(l2InactivityPeriod, 10 minutes, "Incorrect l2InactivityPeriod"); + assertEq(l2AggregationGracePeriod, 2 days, "Incorrect l2AggregationGracePeriod"); + assertEq(skipL2, false, "Incorrect skipL2"); + + assertEq(address(optimisticPlugin.votingToken()), address(votingToken), "Incorrect votingToken"); + assertEq(optimisticPlugin.totalVotingPower(block.timestamp - 1), 10 ether, "Incorrect token supply"); + assertEq(address(optimisticPlugin.taikoL1()), address(taikoL1), "Incorrect taikoL1"); + assertEq(address(optimisticPlugin.taikoBridge()), address(taikoBridge), "Incorrect taikoBridge"); + + // Different timelockPeriod + settings.timelockPeriod = 14 days; + optimisticPlugin = OptimisticTokenVotingPlugin( + createProxyAndCall( + address(OPTIMISTIC_BASE), + abi.encodeCall( + OptimisticTokenVotingPlugin.initialize, (dao, settings, votingToken, address(taikoL1), taikoBridge) + ) + ) + ); + + (minVetoRatio, minDuration, timelockPeriod, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = + optimisticPlugin.governanceSettings(); + assertEq(optimisticPlugin.minVetoRatio(), uint32(RATIO_BASE / 5), "Incorrect minVetoRatio()"); + assertEq(minVetoRatio, uint32(RATIO_BASE / 5), "Incorrect minVetoRatio"); + assertEq(minDuration, 25 days, "Incorrect minDuration"); + assertEq(timelockPeriod, 14 days, "Incorrect timelockPeriod"); assertEq(l2InactivityPeriod, 10 minutes, "Incorrect l2InactivityPeriod"); assertEq(l2AggregationGracePeriod, 2 days, "Incorrect l2AggregationGracePeriod"); assertEq(skipL2, false, "Incorrect skipL2"); @@ -168,11 +200,12 @@ contract OptimisticTokenVotingPluginTest is AragonTest { ) ); - (minVetoRatio, minDuration, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = + (minVetoRatio, minDuration, timelockPeriod, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = optimisticPlugin.governanceSettings(); assertEq(optimisticPlugin.minVetoRatio(), uint32(RATIO_BASE / 5), "Incorrect minVetoRatio()"); assertEq(minVetoRatio, uint32(RATIO_BASE / 5), "Incorrect minVetoRatio"); assertEq(minDuration, 25 days, "Incorrect minDuration"); + assertEq(timelockPeriod, 14 days, "Incorrect timelockPeriod"); assertEq(l2InactivityPeriod, 30 minutes, "Incorrect l2InactivityPeriod"); assertEq(l2AggregationGracePeriod, 2 days, "Incorrect l2AggregationGracePeriod"); assertEq(skipL2, false, "Incorrect skipL2"); @@ -193,11 +226,12 @@ contract OptimisticTokenVotingPluginTest is AragonTest { ) ); - (minVetoRatio, minDuration, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = + (minVetoRatio, minDuration, timelockPeriod, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = optimisticPlugin.governanceSettings(); assertEq(optimisticPlugin.minVetoRatio(), uint32(RATIO_BASE / 5), "Incorrect minVetoRatio()"); assertEq(minVetoRatio, uint32(RATIO_BASE / 5), "Incorrect minVetoRatio"); assertEq(minDuration, 25 days, "Incorrect minDuration"); + assertEq(timelockPeriod, 14 days, "Incorrect timelockPeriod"); assertEq(l2InactivityPeriod, 30 minutes, "Incorrect l2InactivityPeriod"); assertEq(l2AggregationGracePeriod, 5 days, "Incorrect l2AggregationGracePeriod"); assertEq(skipL2, false, "Incorrect skipL2"); @@ -218,11 +252,12 @@ contract OptimisticTokenVotingPluginTest is AragonTest { ) ); - (minVetoRatio, minDuration, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = + (minVetoRatio, minDuration, timelockPeriod, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = optimisticPlugin.governanceSettings(); assertEq(optimisticPlugin.minVetoRatio(), uint32(RATIO_BASE / 5), "Incorrect minVetoRatio()"); assertEq(minVetoRatio, uint32(RATIO_BASE / 5), "Incorrect minVetoRatio"); assertEq(minDuration, 25 days, "Incorrect minDuration"); + assertEq(timelockPeriod, 14 days, "Incorrect timelockPeriod"); assertEq(l2InactivityPeriod, 30 minutes, "Incorrect l2InactivityPeriod"); assertEq(l2AggregationGracePeriod, 5 days, "Incorrect l2AggregationGracePeriod"); assertEq(skipL2, true, "Incorrect skipL2"); @@ -246,11 +281,12 @@ contract OptimisticTokenVotingPluginTest is AragonTest { ) ); - (minVetoRatio, minDuration, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = + (minVetoRatio, minDuration, timelockPeriod, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = optimisticPlugin.governanceSettings(); assertEq(optimisticPlugin.minVetoRatio(), uint32(RATIO_BASE / 5), "Incorrect minVetoRatio()"); assertEq(minVetoRatio, uint32(RATIO_BASE / 5), "Incorrect minVetoRatio"); assertEq(minDuration, 25 days, "Incorrect minDuration"); + assertEq(timelockPeriod, 14 days, "Incorrect timelockPeriod"); assertEq(l2InactivityPeriod, 30 minutes, "Incorrect l2InactivityPeriod"); assertEq(l2AggregationGracePeriod, 5 days, "Incorrect l2AggregationGracePeriod"); assertEq(skipL2, true, "Incorrect skipL2"); @@ -271,11 +307,12 @@ contract OptimisticTokenVotingPluginTest is AragonTest { ) ); - (minVetoRatio, minDuration, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = + (minVetoRatio, minDuration, timelockPeriod, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = optimisticPlugin.governanceSettings(); assertEq(optimisticPlugin.minVetoRatio(), uint32(RATIO_BASE / 5), "Incorrect minVetoRatio()"); assertEq(minVetoRatio, uint32(RATIO_BASE / 5), "Incorrect minVetoRatio"); assertEq(minDuration, 25 days, "Incorrect minDuration"); + assertEq(timelockPeriod, 14 days, "Incorrect timelockPeriod"); assertEq(l2InactivityPeriod, 30 minutes, "Incorrect l2InactivityPeriod"); assertEq(l2AggregationGracePeriod, 5 days, "Incorrect l2AggregationGracePeriod"); assertEq(skipL2, true, "Incorrect skipL2"); @@ -297,11 +334,12 @@ contract OptimisticTokenVotingPluginTest is AragonTest { ) ); - (minVetoRatio, minDuration, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = + (minVetoRatio, minDuration, timelockPeriod, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = optimisticPlugin.governanceSettings(); assertEq(optimisticPlugin.minVetoRatio(), uint32(RATIO_BASE / 5), "Incorrect minVetoRatio()"); assertEq(minVetoRatio, uint32(RATIO_BASE / 5), "Incorrect minVetoRatio"); assertEq(minDuration, 25 days, "Incorrect minDuration"); + assertEq(timelockPeriod, 14 days, "Incorrect timelockPeriod"); assertEq(l2InactivityPeriod, 30 minutes, "Incorrect l2InactivityPeriod"); assertEq(l2AggregationGracePeriod, 5 days, "Incorrect l2AggregationGracePeriod"); assertEq(skipL2, true, "Incorrect skipL2"); @@ -317,6 +355,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 10), minDuration: 10 days, + timelockPeriod: 8 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -381,6 +420,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 10), minDuration: 10 days, + timelockPeriod: 8 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -529,6 +569,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 10), minDuration: 10 days, + timelockPeriod: 8 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -885,6 +926,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 5), minDuration: 10 days, + timelockPeriod: 8 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -1543,9 +1585,10 @@ contract OptimisticTokenVotingPluginTest is AragonTest { function test_CanExecuteReturnsFalseWhenAlreadyExecuted() public { IDAO.Action[] memory actions = new IDAO.Action[](0); uint256 proposalId = optimisticPlugin.createProposal("ipfs://", actions, 0, 4 days); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); vm.warp(block.timestamp + 4 days); - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW()); + vm.warp(block.timestamp + timelockPeriod); assertEq(optimisticPlugin.canExecute(proposalId), true, "The proposal should be executable"); optimisticPlugin.execute(proposalId); @@ -1603,7 +1646,8 @@ contract OptimisticTokenVotingPluginTest is AragonTest { vm.warp(block.timestamp + 4 days); assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal shouldn't be executable"); - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW() - 1); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); + vm.warp(block.timestamp + timelockPeriod - 1); assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal shouldn't be executable"); vm.warp(block.timestamp + 1); @@ -1619,6 +1663,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { (, optimisticPlugin,,, votingToken,,,) = builder.withTokenHolder(alice, 10 ether).withTokenHolder(bob, 10 ether) .withTokenHolder(taikoBridge, 10 ether).withMinVetoRatio(700_000).build(); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); IDAO.Action[] memory actions = new IDAO.Action[](0); uint256 proposalId = optimisticPlugin.createProposal("ipfs://", actions, 0, 4 days); @@ -1632,7 +1677,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal should not be executable"); vm.warp(block.timestamp + builder.l2AggregationGracePeriod()); // grace period over assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal shouldn't be executable"); - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW() - 1); + vm.warp(block.timestamp + timelockPeriod - 1); assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal shouldn't be executable"); vm.warp(block.timestamp + 1); assertEq(optimisticPlugin.canExecute(proposalId), true, "The proposal should be executable"); @@ -1652,7 +1697,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal should not be executable"); vm.warp(block.timestamp + builder.l2AggregationGracePeriod()); // grace period over assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal shouldn't be executable"); - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW() - 1); + vm.warp(block.timestamp + timelockPeriod - 1); assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal shouldn't be executable"); vm.warp(block.timestamp + 1); assertEq(optimisticPlugin.canExecute(proposalId), true, "The proposal should be executable"); @@ -1672,7 +1717,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal should not be executable"); vm.warp(block.timestamp + builder.l2AggregationGracePeriod()); // grace period over assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal shouldn't be executable"); - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW() - 1); + vm.warp(block.timestamp + timelockPeriod - 1); assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal shouldn't be executable"); vm.warp(block.timestamp + 1); assertEq(optimisticPlugin.canExecute(proposalId), true, "The proposal should be executable"); @@ -1683,6 +1728,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { (, optimisticPlugin,,,,,,) = builder.withTokenHolder(alice, 10 ether).withTokenHolder(taikoBridge, 10 ether).withSkipL2().build(); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); IDAO.Action[] memory actions = new IDAO.Action[](0); uint256 proposalId = optimisticPlugin.createProposal("ipfs://", actions, 0, 4 days); @@ -1708,7 +1754,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { assertEq(parameters.unavailableL2, true, "unavailableL2 should be true"); // Exit window almost over - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW() - 1); + vm.warp(block.timestamp + timelockPeriod - 1); assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal shouldn't be executable"); // Exit window over @@ -1743,6 +1789,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { function test_CanExecuteReturnsTrueOtherwise() public { IDAO.Action[] memory actions = new IDAO.Action[](0); uint256 proposalId = optimisticPlugin.createProposal("ipfs://", actions, 0, 4 days); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal shouldn't be executable yet"); @@ -1758,7 +1805,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { optimisticPlugin.getProposal(proposalId); assertEq(parameters.unavailableL2, true, "unavailableL2 should be true"); - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW() - 1); + vm.warp(block.timestamp + timelockPeriod - 1); assertEq(optimisticPlugin.canExecute(proposalId), false, "The proposal shouldn't be executable yet"); // Exit window over @@ -1890,6 +1937,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { function test_ExecuteRevertsBeforeEndedAndExitWindow() public { IDAO.Action[] memory actions = new IDAO.Action[](0); uint256 proposalId = optimisticPlugin.createProposal("ipfs://", actions, 0, 4 days); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); vm.expectRevert( abi.encodeWithSelector(OptimisticTokenVotingPlugin.ProposalExecutionForbidden.selector, proposalId) @@ -1910,7 +1958,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { assertEq(executed, false, "The proposal should not be executed"); // Almost exit window - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW() - 1); + vm.warp(block.timestamp + timelockPeriod - 1); vm.expectRevert( abi.encodeWithSelector(OptimisticTokenVotingPlugin.ProposalExecutionForbidden.selector, proposalId) ); @@ -1930,6 +1978,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { function test_ExecuteRevertsWhenDefeated_L1Only() public { IDAO.Action[] memory actions = new IDAO.Action[](0); uint256 proposalId = optimisticPlugin.createProposal("ipfs://", actions, 0, 4 days); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); optimisticPlugin.veto(proposalId); @@ -1942,7 +1991,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { assertEq(executed, false, "The proposal should not be executed"); vm.warp(block.timestamp + 4 days); - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW()); + vm.warp(block.timestamp + timelockPeriod); vm.expectRevert( abi.encodeWithSelector(OptimisticTokenVotingPlugin.ProposalExecutionForbidden.selector, proposalId) @@ -1964,6 +2013,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { (, optimisticPlugin,,,,,,) = builder.withTokenHolder(alice, 10 ether).withTokenHolder(bob, 10 ether) .withTokenHolder(taikoBridge, 10 ether).withMinVetoRatio(700_000).build(); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); IDAO.Action[] memory actions = new IDAO.Action[](0); uint256 proposalId = optimisticPlugin.createProposal("ipfs://", actions, 0, 4 days); @@ -1977,7 +2027,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { // bridge supply counts but doesn't veto vm.warp(block.timestamp + 4 days); // end - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW()); + vm.warp(block.timestamp + timelockPeriod); vm.expectRevert( abi.encodeWithSelector(OptimisticTokenVotingPlugin.ProposalExecutionForbidden.selector, proposalId) ); @@ -2002,7 +2052,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { optimisticPlugin.veto(proposalId); // 100% (above 70%) vm.warp(block.timestamp + 4 days); // end - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW()); + vm.warp(block.timestamp + timelockPeriod); vm.expectRevert( abi.encodeWithSelector(OptimisticTokenVotingPlugin.ProposalExecutionForbidden.selector, proposalId) ); @@ -2035,7 +2085,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { optimisticPlugin.execute(proposalId); vm.warp(block.timestamp + builder.l2AggregationGracePeriod()); // grace period over - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW()); + vm.warp(block.timestamp + timelockPeriod); vm.expectRevert( abi.encodeWithSelector(OptimisticTokenVotingPlugin.ProposalExecutionForbidden.selector, proposalId) ); @@ -2045,9 +2095,10 @@ contract OptimisticTokenVotingPluginTest is AragonTest { function test_ExecuteRevertsWhenAlreadyExecuted() public { IDAO.Action[] memory actions = new IDAO.Action[](0); uint256 proposalId = optimisticPlugin.createProposal("ipfs://", actions, 0, 4 days); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); vm.warp(block.timestamp + 4 days); - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW()); + vm.warp(block.timestamp + timelockPeriod); optimisticPlugin.execute(proposalId); @@ -2068,6 +2119,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { IDAO.Action[] memory actions = new IDAO.Action[](0); uint256 proposalId = optimisticPlugin.createProposal("ipfs://", actions, 0, 4 days); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); (bool open, bool executed, OptimisticTokenVotingPlugin.ProposalParameters memory parameters,,,,) = optimisticPlugin.getProposal(proposalId); @@ -2090,7 +2142,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { assertEq(parameters.unavailableL2, true, "unavailableL2 should be true"); // Exit window almost over - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW() - 1); + vm.warp(block.timestamp + timelockPeriod - 1); vm.expectRevert( abi.encodeWithSelector(OptimisticTokenVotingPlugin.ProposalExecutionForbidden.selector, proposalId) ); @@ -2121,6 +2173,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { IDAO.Action[] memory actions = new IDAO.Action[](0); uint256 proposalId = optimisticPlugin.createProposal("ipfs://", actions, 0, 4 days); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); (bool open, bool executed, OptimisticTokenVotingPlugin.ProposalParameters memory parameters,,,,) = optimisticPlugin.getProposal(proposalId); @@ -2169,7 +2222,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { assertEq(parameters.unavailableL2, false, "unavailableL2 should be false"); // Exit window almost over - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW() - 1); + vm.warp(block.timestamp + timelockPeriod - 1); vm.expectRevert( abi.encodeWithSelector(OptimisticTokenVotingPlugin.ProposalExecutionForbidden.selector, proposalId) ); @@ -2195,9 +2248,10 @@ contract OptimisticTokenVotingPluginTest is AragonTest { function test_ExecuteSucceedsOtherwise() public { IDAO.Action[] memory actions = new IDAO.Action[](0); uint256 proposalId = optimisticPlugin.createProposal("ipfs://", actions, 0, 4 days); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); vm.warp(block.timestamp + 4 days); - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW()); + vm.warp(block.timestamp + timelockPeriod); optimisticPlugin.execute(proposalId); } @@ -2205,6 +2259,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { function test_ExecuteMarksTheProposalAsExecuted() public { IDAO.Action[] memory actions = new IDAO.Action[](0); uint256 proposalId = optimisticPlugin.createProposal("ipfs://", actions, 0, 4 days); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); (, bool executed,,,,,) = optimisticPlugin.getProposal(proposalId); assertEq(executed, false, "The proposal should not be executed"); @@ -2214,7 +2269,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { (, executed,,,,,) = optimisticPlugin.getProposal(proposalId); assertEq(executed, false, "The proposal should not be executed"); - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW()); + vm.warp(block.timestamp + timelockPeriod); (, executed,,,,,) = optimisticPlugin.getProposal(proposalId); assertEq(executed, false, "The proposal should not be executed"); @@ -2228,9 +2283,10 @@ contract OptimisticTokenVotingPluginTest is AragonTest { function test_ExecuteEmitsAnEvent() public { IDAO.Action[] memory actions = new IDAO.Action[](0); uint256 proposalId = optimisticPlugin.createProposal("ipfs://", actions, 0, 4 days); + (,, uint32 timelockPeriod,,,) = optimisticPlugin.governanceSettings(); vm.warp(block.timestamp + 4 days); - vm.warp(block.timestamp + optimisticPlugin.EXIT_WINDOW()); + vm.warp(block.timestamp + timelockPeriod); vm.expectEmit(); emit ProposalExecuted(proposalId); @@ -2243,6 +2299,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 5), minDuration: 15 days, + timelockPeriod: 8 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -2274,6 +2331,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: 0, minDuration: 10 days, + timelockPeriod: 8 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -2291,6 +2349,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE + 1), minDuration: 10 days, + timelockPeriod: 8 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -2308,6 +2367,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 10), minDuration: 365 days + 1, + timelockPeriod: 8 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -2321,6 +2381,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { newSettings = OptimisticTokenVotingPlugin.OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 10), minDuration: 500 days, + timelockPeriod: 8 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -2334,6 +2395,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { newSettings = OptimisticTokenVotingPlugin.OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 10), minDuration: 1000 days, + timelockPeriod: 8 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -2353,6 +2415,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 5), minDuration: 15 days, + timelockPeriod: 8 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -2374,6 +2437,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { newSettings = OptimisticTokenVotingPlugin.OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 5), minDuration: 19 days, + timelockPeriod: 8 days, l2InactivityPeriod: 50 minutes, l2AggregationGracePeriod: 20 days, skipL2: true @@ -2396,9 +2460,10 @@ contract OptimisticTokenVotingPluginTest is AragonTest { function test_GovernanceSettingsReturnsTheRightValues() public { ( uint32 minVetoRatio, - uint64 minDuration, - uint64 l2InactivityPeriod, - uint64 l2AggregationGracePeriod, + uint32 minDuration, + uint32 timelockPeriod, + uint32 l2InactivityPeriod, + uint32 l2AggregationGracePeriod, bool skipL2 ) = optimisticPlugin.governanceSettings(); @@ -2413,6 +2478,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 2), minDuration: 0, + timelockPeriod: 8 days, l2InactivityPeriod: 15 minutes, l2AggregationGracePeriod: 73 days, skipL2: true @@ -2428,7 +2494,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { ) ); - (minVetoRatio, minDuration, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = + (minVetoRatio, minDuration, timelockPeriod, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = optimisticPlugin.governanceSettings(); assertEq(minVetoRatio, uint32(RATIO_BASE / 2)); assertEq(minDuration, 0); @@ -2444,6 +2510,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { newSettings = OptimisticTokenVotingPlugin.OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 5), minDuration: 15 days, + timelockPeriod: 8 days, l2InactivityPeriod: 0, l2AggregationGracePeriod: 1234 minutes, skipL2: false @@ -2451,7 +2518,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { optimisticPlugin.updateOptimisticGovernanceSettings(newSettings); - (minVetoRatio, minDuration, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = + (minVetoRatio, minDuration, timelockPeriod, l2InactivityPeriod, l2AggregationGracePeriod, skipL2) = optimisticPlugin.governanceSettings(); assertEq(minVetoRatio, uint32(RATIO_BASE / 5)); assertEq(minDuration, 15 days); @@ -2492,6 +2559,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 5), minDuration: 15 days, + timelockPeriod: 8 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -2543,6 +2611,7 @@ contract OptimisticTokenVotingPluginTest is AragonTest { .OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 5), minDuration: 15 days, + timelockPeriod: 8 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false diff --git a/test/OptimisticTokenVotingPluginSetup.t.sol b/test/OptimisticTokenVotingPluginSetup.t.sol index 86348a2..e4c3a3c 100644 --- a/test/OptimisticTokenVotingPluginSetup.t.sol +++ b/test/OptimisticTokenVotingPluginSetup.t.sol @@ -58,6 +58,7 @@ contract OptimisticTokenVotingPluginSetupTest is Test { votingSettings = OptimisticTokenVotingPlugin.OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 10), minDuration: 5 days, + timelockPeriod: 7 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -101,7 +102,7 @@ contract OptimisticTokenVotingPluginSetupTest is Test { ); bytes memory expected = - hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000697800000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000000000000002a3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000066666666000000000000000000000000000000000000000000000000000000005555555500000000000000000000000000000000000000000000000000000000000d2f00000000000000000000000000000000000000000000000000000000123456789000000000000000000000000000000000000000000000000000000023456789010000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000d5772617070656420546f6b656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000377544b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000697800000000000000000000000000000000000000000000000000000000000093a800000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000066666666000000000000000000000000000000000000000000000000000000005555555500000000000000000000000000000000000000000000000000000000000d2f00000000000000000000000000000000000000000000000000000000123456789000000000000000000000000000000000000000000000000000000023456789010000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000d5772617070656420546f6b656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000377544b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; assertEq(output, expected, "Incorrect encoded bytes"); } @@ -110,6 +111,7 @@ contract OptimisticTokenVotingPluginSetupTest is Test { votingSettings = OptimisticTokenVotingPlugin.OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 5), minDuration: 60 * 60 * 24 * 5, + timelockPeriod: 14 days, l2InactivityPeriod: 20 minutes, l2AggregationGracePeriod: 20 days, skipL2: false @@ -128,13 +130,14 @@ contract OptimisticTokenVotingPluginSetupTest is Test { ); bytes memory expected = - hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000030d40000000000000000000000000000000000000000000000000000000000006978000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000001a5e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000066666666000000000000000000000000000000000000000000000000000000005555555500000000000000000000000000000000000000000000000000000000000d2f00000000000000000000000000000000000000000000000000000000123456789000000000000000000000000000000000000000000000000000000023456789010000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000d5772617070656420546f6b656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000377544b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000030d400000000000000000000000000000000000000000000000000000000000069780000000000000000000000000000000000000000000000000000000000012750000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000001a5e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000066666666000000000000000000000000000000000000000000000000000000005555555500000000000000000000000000000000000000000000000000000000000d2f00000000000000000000000000000000000000000000000000000000123456789000000000000000000000000000000000000000000000000000000023456789010000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000d5772617070656420546f6b656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000377544b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; assertEq(output, expected, "Incorrect encoded bytes"); // Custom 2 (skip L2) votingSettings = OptimisticTokenVotingPlugin.OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 5), minDuration: 60 * 60 * 24 * 5, + timelockPeriod: 14 days, l2InactivityPeriod: 20 minutes, l2AggregationGracePeriod: 20 days, skipL2: true @@ -153,7 +156,7 @@ contract OptimisticTokenVotingPluginSetupTest is Test { ); expected = - hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000030d40000000000000000000000000000000000000000000000000000000000006978000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000001a5e000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000066666666000000000000000000000000000000000000000000000000000000005555555500000000000000000000000000000000000000000000000000000000000d2f00000000000000000000000000000000000000000000000000000000123456789000000000000000000000000000000000000000000000000000000023456789010000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000d5772617070656420546f6b656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000377544b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000030d400000000000000000000000000000000000000000000000000000000000069780000000000000000000000000000000000000000000000000000000000012750000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000001a5e00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000066666666000000000000000000000000000000000000000000000000000000005555555500000000000000000000000000000000000000000000000000000000000d2f00000000000000000000000000000000000000000000000000000000123456789000000000000000000000000000000000000000000000000000000023456789010000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000d5772617070656420546f6b656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000377544b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; assertEq(output, expected, "Incorrect encoded bytes"); } @@ -178,7 +181,7 @@ contract OptimisticTokenVotingPluginSetupTest is Test { ); bytes memory expected = - hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000697800000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000000000000002a3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000066666666000000000000000000000000000000000000000000000000000000005555555500000000000000000000000000000000000000000000000000000000000d2f00000000000000000000000000000000000000000000000000000000123456789000000000000000000000000000000000000000000000000000000023456789010000000000000000000000000000000000000000000000000000000000005678000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001057726170706564204e657720436f696e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004774e434e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000697800000000000000000000000000000000000000000000000000000000000093a800000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000066666666000000000000000000000000000000000000000000000000000000005555555500000000000000000000000000000000000000000000000000000000000d2f00000000000000000000000000000000000000000000000000000000123456789000000000000000000000000000000000000000000000000000000023456789010000000000000000000000000000000000000000000000000000000000005678000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001057726170706564204e657720436f696e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004774e434e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; assertEq(output, expected, "Incorrect encoded bytes"); } @@ -204,7 +207,7 @@ contract OptimisticTokenVotingPluginSetupTest is Test { ); bytes memory expected = - hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000697800000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000123400000000000000000000000000000000000000000000000000000000000056780000000000000000000000000000000000000000000000000000000000069780000000000000000000000000000000000000000000000000000000123456789000000000000000000000000000000000000000000000000000000023456789010000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000d5772617070656420546f6b656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000377544b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000006789000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000499602d2"; + hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000697800000000000000000000000000000000000000000000000000000000000093a800000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000123400000000000000000000000000000000000000000000000000000000000056780000000000000000000000000000000000000000000000000000000000069780000000000000000000000000000000000000000000000000000000123456789000000000000000000000000000000000000000000000000000000023456789010000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000d5772617070656420546f6b656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000377544b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000006789000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000499602d2"; assertEq(output, expected, "Incorrect encoded bytes"); } @@ -226,7 +229,7 @@ contract OptimisticTokenVotingPluginSetupTest is Test { ); bytes memory expected = - hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000697800000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000000000000002a30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000002222000000000000000000000000000000000000000000000000000000000013c680000000000000000000000000000000000000000000000000000000000056789000000000000000000000000000000000000000000000000000000023456789010000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000d5772617070656420546f6b656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000377544b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000697800000000000000000000000000000000000000000000000000000000000093a800000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000002222000000000000000000000000000000000000000000000000000000000013c680000000000000000000000000000000000000000000000000000000000056789000000000000000000000000000000000000000000000000000000023456789010000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000d5772617070656420546f6b656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000377544b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; assertEq(output, expected, "Incorrect encoded bytes"); } @@ -234,6 +237,7 @@ contract OptimisticTokenVotingPluginSetupTest is Test { votingSettings = OptimisticTokenVotingPlugin.OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 4), minDuration: 10 days, + timelockPeriod: 12 days, l2InactivityPeriod: 22 minutes, l2AggregationGracePeriod: 24 days, skipL2: false @@ -277,6 +281,7 @@ contract OptimisticTokenVotingPluginSetupTest is Test { _decodedInstallationParams.votingSettings.minVetoRatio, uint32(RATIO_BASE / 4), "Incorrect minVetoRatio" ); assertEq(_decodedInstallationParams.votingSettings.minDuration, 10 days, "Incorrect minDuration"); + assertEq(_decodedInstallationParams.votingSettings.timelockPeriod, 12 days, "Incorrect timelockPeriod"); assertEq( _decodedInstallationParams.votingSettings.l2InactivityPeriod, 22 minutes, "Incorrect l2InactivityPeriod" ); @@ -317,6 +322,7 @@ contract OptimisticTokenVotingPluginSetupTest is Test { votingSettings = OptimisticTokenVotingPlugin.OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 5), minDuration: 12 days, + timelockPeriod: 9 days, l2InactivityPeriod: 44 minutes, l2AggregationGracePeriod: 45 days, skipL2: true @@ -364,6 +370,7 @@ contract OptimisticTokenVotingPluginSetupTest is Test { _decodedInstallationParams.votingSettings.minVetoRatio, uint32(RATIO_BASE / 5), "Incorrect minVetoRatio" ); assertEq(_decodedInstallationParams.votingSettings.minDuration, 12 days, "Incorrect minDuration"); + assertEq(_decodedInstallationParams.votingSettings.timelockPeriod, 9 days, "Incorrect timelockPeriod"); assertEq( _decodedInstallationParams.votingSettings.l2InactivityPeriod, 44 minutes, "Incorrect l2InactivityPeriod" ); @@ -490,6 +497,7 @@ contract OptimisticTokenVotingPluginSetupTest is Test { votingSettings = OptimisticTokenVotingPlugin.OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 4), minDuration: 10 days, + timelockPeriod: 7 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false @@ -587,6 +595,7 @@ contract OptimisticTokenVotingPluginSetupTest is Test { votingSettings = OptimisticTokenVotingPlugin.OptimisticGovernanceSettings({ minVetoRatio: uint32(RATIO_BASE / 4), minDuration: 10 days, + timelockPeriod: 7 days, l2InactivityPeriod: 10 minutes, l2AggregationGracePeriod: 2 days, skipL2: false diff --git a/test/helpers/DaoBuilder.sol b/test/helpers/DaoBuilder.sol index c51c5b8..5f847b6 100644 --- a/test/helpers/DaoBuilder.sol +++ b/test/helpers/DaoBuilder.sol @@ -43,9 +43,10 @@ contract DaoBuilder is Test { MintEntry[] public tokenHolders; uint32 public minVetoRatio = uint32(RATIO_BASE / 10); // 10% - uint64 public minDuration = 4 days; - uint64 public l2InactivityPeriod = 10 minutes; - uint64 public l2AggregationGracePeriod = 2 days; + uint32 public minDuration = 4 days; + uint32 public timelockPeriod = 7 days; + uint32 public l2InactivityPeriod = 10 minutes; + uint32 public l2AggregationGracePeriod = 2 days; bool public skipL2 = false; bool public onlyListed = true; @@ -99,17 +100,22 @@ contract DaoBuilder is Test { return this; } + function withTimelock(uint32 newTimeLock) public returns (DaoBuilder) { + timelockPeriod = newTimeLock; + return this; + } + function withExpiration(uint64 newExpirationPeriod) public returns (DaoBuilder) { multisigProposalExpirationPeriod = newExpirationPeriod; return this; } - function withL2InactivityPeriod(uint64 newL2InactivityPeriod) public returns (DaoBuilder) { + function withL2InactivityPeriod(uint32 newL2InactivityPeriod) public returns (DaoBuilder) { l2InactivityPeriod = newL2InactivityPeriod; return this; } - function withL2AggregationGracePeriod(uint64 newL2AggregationGracePeriod) public returns (DaoBuilder) { + function withL2AggregationGracePeriod(uint32 newL2AggregationGracePeriod) public returns (DaoBuilder) { l2AggregationGracePeriod = newL2AggregationGracePeriod; return this; } @@ -208,6 +214,7 @@ contract DaoBuilder is Test { OptimisticTokenVotingPlugin.OptimisticGovernanceSettings({ minVetoRatio: minVetoRatio, minDuration: minDuration, + timelockPeriod: timelockPeriod, l2InactivityPeriod: l2InactivityPeriod, l2AggregationGracePeriod: l2AggregationGracePeriod, skipL2: skipL2 diff --git a/test/integration/TaikoDaoFactory.t.sol b/test/integration/TaikoDaoFactory.t.sol index 2c1024d..6870b7c 100644 --- a/test/integration/TaikoDaoFactory.t.sol +++ b/test/integration/TaikoDaoFactory.t.sol @@ -47,12 +47,13 @@ contract TaikoDaoFactoryTest is AragonTest { tokenAddress: tokenAddress, taikoL1ContractAddress: address(taikoL1ContractAddress), // address taikoBridgeAddress: taikoBridgeAddress, // address - l2InactivityPeriod: 10 minutes, // uint64 - l2AggregationGracePeriod: 2 days, // uint64 + timelockPeriod: 7 days, + l2InactivityPeriod: 10 minutes, // uint32 + l2AggregationGracePeriod: 2 days, // uint32 skipL2: false, // Voting settings minVetoRatio: 200_000, // uint32 - minStdProposalDuration: 10 days, // uint64 + minStdProposalDuration: 10 days, // uint32 minStdApprovals: 7, // uint16 minEmergencyApprovals: 11, // uint16 // OSx contracts @@ -83,6 +84,7 @@ contract TaikoDaoFactoryTest is AragonTest { "Incorrect taikoL1ContractAddress" ); assertEq(actualSettings.taikoBridgeAddress, creationSettings.taikoBridgeAddress, "Incorrect taikoBridgeAddress"); + assertEq(actualSettings.timelockPeriod, creationSettings.timelockPeriod, "Incorrect timelockPeriod"); assertEq(actualSettings.l2InactivityPeriod, creationSettings.l2InactivityPeriod, "Incorrect l2InactivityPeriod"); assertEq( actualSettings.l2AggregationGracePeriod, @@ -177,12 +179,13 @@ contract TaikoDaoFactoryTest is AragonTest { tokenAddress: tokenAddress, taikoL1ContractAddress: address(taikoL1ContractAddress), // address taikoBridgeAddress: taikoBridgeAddress, // address - l2InactivityPeriod: 27 minutes, // uint64 - l2AggregationGracePeriod: 77 days, // uint64 + timelockPeriod: 14 days, + l2InactivityPeriod: 27 minutes, // uint32 + l2AggregationGracePeriod: 77 days, // uint32 skipL2: false, // Voting settings minVetoRatio: 456_000, // uint32 - minStdProposalDuration: 14 days, // uint64 + minStdProposalDuration: 14 days, // uint32 minStdApprovals: 4, // uint16 minEmergencyApprovals: 27, // uint16 // OSx contracts @@ -213,6 +216,7 @@ contract TaikoDaoFactoryTest is AragonTest { "Incorrect taikoL1ContractAddress" ); assertEq(actualSettings.taikoBridgeAddress, creationSettings.taikoBridgeAddress, "Incorrect taikoBridgeAddress"); + assertEq(actualSettings.timelockPeriod, creationSettings.timelockPeriod, "Incorrect timelockPeriod"); assertEq(actualSettings.l2InactivityPeriod, creationSettings.l2InactivityPeriod, "Incorrect l2InactivityPeriod"); assertEq( actualSettings.l2AggregationGracePeriod, @@ -330,12 +334,13 @@ contract TaikoDaoFactoryTest is AragonTest { tokenAddress: tokenAddress, taikoL1ContractAddress: address(taikoL1ContractAddress), // address taikoBridgeAddress: taikoBridgeAddress, // address - l2InactivityPeriod: 10 minutes, // uint64 - l2AggregationGracePeriod: 2 days, // uint64 + timelockPeriod: 20 days, + l2InactivityPeriod: 10 minutes, // uint32 + l2AggregationGracePeriod: 2 days, // uint32 skipL2: false, // Voting settings minVetoRatio: 200_000, // uint32 - minStdProposalDuration: 10 days, // uint64 + minStdProposalDuration: 10 days, // uint32 minStdApprovals: 7, // uint16 minEmergencyApprovals: 11, // uint16 // OSx contracts @@ -395,7 +400,7 @@ contract TaikoDaoFactoryTest is AragonTest { ); // Signer list - + assertEq(deployment.signerList.addresslistLength(), 13, "Invalid addresslistLength"); for (uint256 i = 0; i < 13; i++) { assertEq(deployment.signerList.isListed(multisigMembers[i]), true, "Should be a member"); @@ -471,14 +476,16 @@ contract TaikoDaoFactoryTest is AragonTest { { ( uint32 minVetoRatio, - uint64 minDuration, - uint64 l2InactivityPeriod, - uint64 l2AggregationGracePeriod, + uint32 minDuration, + uint32 timelockPeriod, + uint32 l2InactivityPeriod, + uint32 l2AggregationGracePeriod, bool skipL2 ) = deployment.optimisticTokenVotingPlugin.governanceSettings(); assertEq(minVetoRatio, 200_000, "Invalid minVetoRatio"); assertEq(minDuration, 0, "Invalid minDuration"); // 10 days is enforced on the condition contract + assertEq(timelockPeriod, 20 days, "Invalid timelockPeriod"); assertEq(l2InactivityPeriod, 10 minutes, "Invalid l2InactivityPeriod"); assertEq(l2AggregationGracePeriod, 2 days, "Invalid l2AggregationGracePeriod"); assertEq(skipL2, false, "Invalid skipL2"); @@ -573,12 +580,13 @@ contract TaikoDaoFactoryTest is AragonTest { tokenAddress: tokenAddress, taikoL1ContractAddress: address(taikoL1ContractAddress), // address taikoBridgeAddress: taikoBridgeAddress, // address - l2InactivityPeriod: 27 minutes, // uint64 - l2AggregationGracePeriod: 3 days, // uint64 + timelockPeriod: 9 days, // uint32 + l2InactivityPeriod: 27 minutes, // uint32 + l2AggregationGracePeriod: 3 days, // uint32 skipL2: true, // Voting settings minVetoRatio: 456_000, // uint32 - minStdProposalDuration: 21 days, // uint64 + minStdProposalDuration: 21 days, // uint32 minStdApprovals: 9, // uint16 minEmergencyApprovals: 15, // uint16 // OSx contracts @@ -714,14 +722,16 @@ contract TaikoDaoFactoryTest is AragonTest { { ( uint32 minVetoRatio, - uint64 minDuration, - uint64 l2InactivityPeriod, - uint64 l2AggregationGracePeriod, + uint32 minDuration, + uint32 timelockPeriod, + uint32 l2InactivityPeriod, + uint32 l2AggregationGracePeriod, bool skipL2 ) = deployment.optimisticTokenVotingPlugin.governanceSettings(); assertEq(minVetoRatio, 456_000, "Invalid minVetoRatio"); assertEq(minDuration, 0, "Invalid minDuration"); // 10 days is enforced on the condition contract + assertEq(timelockPeriod, 9 days, "Invalid timelockPeriod"); assertEq(l2InactivityPeriod, 27 minutes, "Invalid l2InactivityPeriod"); assertEq(l2AggregationGracePeriod, 3 days, "Invalid l2AggregationGracePeriod"); assertEq(skipL2, true, "Invalid skipL2"); @@ -816,12 +826,13 @@ contract TaikoDaoFactoryTest is AragonTest { tokenAddress: tokenAddress, taikoL1ContractAddress: address(taikoL1ContractAddress), // address taikoBridgeAddress: taikoBridgeAddress, // address - l2InactivityPeriod: 10 minutes, // uint64 - l2AggregationGracePeriod: 2 days, // uint64 + timelockPeriod: 11 days, + l2InactivityPeriod: 10 minutes, // uint32 + l2AggregationGracePeriod: 2 days, // uint32 skipL2: false, // Voting settings minVetoRatio: 200_000, // uint32 - minStdProposalDuration: 10 days, // uint64 + minStdProposalDuration: 10 days, // uint32 minStdApprovals: 7, // uint16 minEmergencyApprovals: 11, // uint16 // OSx contracts From 2065c030cf47b30746328ea792f83eeb3534193d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8r=E2=88=82=C2=A1?= Date: Thu, 28 Nov 2024 13:53:02 +0700 Subject: [PATCH 2/4] Reducing the uint size needed for periods and durations --- src/EmergencyMultisig.sol | 4 ++-- src/Multisig.sol | 8 ++++---- test/EmergencyMultisig.t.sol | 4 ++-- test/Multisig.t.sol | 6 +++--- test/helpers/DaoBuilder.sol | 6 +++--- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/EmergencyMultisig.sol b/src/EmergencyMultisig.sol index 6f26bf8..7a02f6e 100644 --- a/src/EmergencyMultisig.sol +++ b/src/EmergencyMultisig.sol @@ -58,7 +58,7 @@ contract EmergencyMultisig is IEmergencyMultisig, PluginUUPSUpgradeable, Proposa bool onlyListed; uint16 minApprovals; SignerList signerList; - uint64 proposalExpirationPeriod; + uint32 proposalExpirationPeriod; // uint32 is enough, not a timestamp } /// @notice The ID of the permission required to call the `addAddresses` and `removeAddresses` functions. @@ -128,7 +128,7 @@ contract EmergencyMultisig is IEmergencyMultisig, PluginUUPSUpgradeable, Proposa /// @param signerList The contract defining who is a member and/or who is appointed as a decryption wallet /// @param proposalExpirationPeriod The amount of seconds after which a non executed proposal expires. event MultisigSettingsUpdated( - bool onlyListed, uint16 indexed minApprovals, SignerList signerList, uint64 proposalExpirationPeriod + bool onlyListed, uint16 indexed minApprovals, SignerList signerList, uint32 proposalExpirationPeriod ); /// @notice Initializes Release 1, Build 1. diff --git a/src/Multisig.sol b/src/Multisig.sol index 27c529e..976039b 100644 --- a/src/Multisig.sol +++ b/src/Multisig.sol @@ -59,9 +59,9 @@ contract Multisig is IMultisig, PluginUUPSUpgradeable, ProposalUpgradeable { struct MultisigSettings { bool onlyListed; uint16 minApprovals; - uint64 destinationProposalDuration; + uint32 destinationProposalDuration; // uint32 is enough, not a timestamp SignerList signerList; - uint64 proposalExpirationPeriod; + uint32 proposalExpirationPeriod; // uint32 is enough, not a timestamp } /// @notice The ID of the permission required to call the `addAddresses` and `removeAddresses` functions. @@ -124,9 +124,9 @@ contract Multisig is IMultisig, PluginUUPSUpgradeable, ProposalUpgradeable { event MultisigSettingsUpdated( bool onlyListed, uint16 indexed minApprovals, - uint64 destinationProposalDuration, + uint32 destinationProposalDuration, SignerList signerList, - uint64 proposalExpirationPeriod + uint32 proposalExpirationPeriod ); /// @notice Initializes Release 1, Build 1. diff --git a/test/EmergencyMultisig.t.sol b/test/EmergencyMultisig.t.sol index 86c3e76..822b502 100644 --- a/test/EmergencyMultisig.t.sol +++ b/test/EmergencyMultisig.t.sol @@ -20,7 +20,7 @@ import {IProposal} from "@aragon/osx/core/plugin/proposal/IProposal.sol"; import {IPlugin} from "@aragon/osx/core/plugin/IPlugin.sol"; import {IEmergencyMultisig} from "../src/interfaces/IEmergencyMultisig.sol"; -uint64 constant EMERGENCY_MULTISIG_PROPOSAL_EXPIRATION_PERIOD = 10 days; +uint32 constant EMERGENCY_MULTISIG_PROPOSAL_EXPIRATION_PERIOD = 10 days; contract EmergencyMultisigTest is AragonTest { DaoBuilder builder; @@ -38,7 +38,7 @@ contract EmergencyMultisigTest is AragonTest { error InvalidActions(uint256 proposalId); event MultisigSettingsUpdated( - bool onlyListed, uint16 indexed minApprovals, SignerList signerList, uint64 proposalExpirationPeriod + bool onlyListed, uint16 indexed minApprovals, SignerList signerList, uint32 proposalExpirationPeriod ); event EmergencyProposalCreated(uint256 indexed proposalId, address indexed creator, bytes encryptedPayloadURI); diff --git a/test/Multisig.t.sol b/test/Multisig.t.sol index 04f2a38..c3a25ca 100644 --- a/test/Multisig.t.sol +++ b/test/Multisig.t.sol @@ -20,7 +20,7 @@ import {IProposal} from "@aragon/osx/core/plugin/proposal/IProposal.sol"; import {IPlugin} from "@aragon/osx/core/plugin/IPlugin.sol"; import {IMultisig} from "../src/interfaces/IMultisig.sol"; -uint64 constant MULTISIG_PROPOSAL_EXPIRATION_PERIOD = 10 days; +uint32 constant MULTISIG_PROPOSAL_EXPIRATION_PERIOD = 10 days; uint32 constant DESTINATION_PROPOSAL_DURATION = 9 days; contract MultisigTest is AragonTest { @@ -41,9 +41,9 @@ contract MultisigTest is AragonTest { event MultisigSettingsUpdated( bool onlyListed, uint16 indexed minApprovals, - uint64 destinationProposalDuration, + uint32 destinationProposalDuration, SignerList signerList, - uint64 proposalExpirationPeriod + uint32 proposalExpirationPeriod ); // Multisig and OptimisticTokenVotingPlugin's event event ProposalCreated( diff --git a/test/helpers/DaoBuilder.sol b/test/helpers/DaoBuilder.sol index 5f847b6..a435c88 100644 --- a/test/helpers/DaoBuilder.sol +++ b/test/helpers/DaoBuilder.sol @@ -51,8 +51,8 @@ contract DaoBuilder is Test { bool public onlyListed = true; uint16 public minApprovals = 1; - uint64 public stdProposalDuration = 10 days; - uint64 multisigProposalExpirationPeriod = 10 days; + uint32 public stdProposalDuration = 10 days; + uint32 public multisigProposalExpirationPeriod = 10 days; function withDaoOwner(address newOwner) public returns (DaoBuilder) { owner = newOwner; @@ -105,7 +105,7 @@ contract DaoBuilder is Test { return this; } - function withExpiration(uint64 newExpirationPeriod) public returns (DaoBuilder) { + function withExpiration(uint32 newExpirationPeriod) public returns (DaoBuilder) { multisigProposalExpirationPeriod = newExpirationPeriod; return this; } From 4080713227ea93670f11faa075fc16c4332b36fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8r=E2=88=82=C2=A1?= Date: Thu, 28 Nov 2024 14:15:37 +0700 Subject: [PATCH 3/4] Test deployment info --- DEPLOYMENTS.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/DEPLOYMENTS.md b/DEPLOYMENTS.md index e45d5bf..569128f 100644 --- a/DEPLOYMENTS.md +++ b/DEPLOYMENTS.md @@ -4,6 +4,42 @@ ## Holesly +### November 28th 2024 + +Deployment for internal testing: +- Exit window of 7 days (parameterizable) +- L2 disabled +- Using a pre-release voting token + +``` + + Deploying from: 0x424797Ed6d902E17b9180BFcEF452658e148e0Ab + Chain ID: 17000 + Using test token settings + Minting test tokens for the multisig members and the bridge + + Factory: 0x7b9B81258d4b52Fb6D4Fb3C597bCeD2652F00bc8 + + DAO: 0x9Fe7b040cfD4CA67BB44714aa9c9D2F5234780BE + Voting token: 0x690b92470Aa1500CFc64af5adAb4A9D4c0a0a5f0 + Taiko Bridge: 0x0000000000000000000000000000001234567890 + + Plugins + - Multisig plugin: 0xEAfaB9a95dC75C51d94b2cad2D675296914fA8a6 + - Emergency multisig plugin: 0xF0847b600eebe43da7FD6bA1C9E325EC8408cB4F + - Optimistic token voting plugin: 0x892d99d271844A7C39757adcD177fbE2EFD3adbb + + Helpers + - Signer list 0x08e2003Aab54d8C981A3bc5c48bB121B9eb57467 + - Encryption registry 0x5Ec236003Cf8493cF2621E5daCAbD60f0a7A31Ae + - Delegation wall 0xe2e3b8a20048F699d40c1d4394BE62B30560fa6f + + Plugin repositories + - Multisig plugin repository: 0xe797aFeABf9Cf5a0e86EA2B5D3a5F20397A98514 + - Emergency multisig plugin repository: 0x87322002988a7AD7864cF89233b43D7CAE9289DA + - Optimistic token voting plugin repository: 0x2a0fa7CBB75444DA374169e9dd6Fee3330082B99 +``` + ### November 18th 2024 Deployment for internal testing: From 86a4ce96b4f25a38d125d134b9415de4b5125085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8r=E2=88=82=C2=A1?= Date: Fri, 29 Nov 2024 14:49:28 +0700 Subject: [PATCH 4/4] Updating the example .env file --- .env.example | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index a242adc..00441d1 100644 --- a/.env.example +++ b/.env.example @@ -26,9 +26,9 @@ TIME_LOCK_PERIOD="604800" # in seconds (7 days) L2_INACTIVITY_PERIOD="600" # in seconds (10 minutes) L2_AGGREGATION_GRACE_PERIOD="172800" # in seconds (2 days) SKIP_L2=true # Determines whether vote aggregation from the L2 will be disabled -MIN_STD_PROPOSAL_DURATION="864000" # in seconds (10 days) -MIN_STD_APPROVALS="5" # How many multisig approvals are required -MIN_EMERGENCY_APPROVALS="10" # How many emergency multisig approvals are required +MIN_STD_PROPOSAL_DURATION="1209600" # in seconds (14 days) +MIN_STD_APPROVALS="3" # How many multisig approvals are required +MIN_EMERGENCY_APPROVALS="6" # How many emergency multisig approvals are required MULTISIG_PROPOSAL_EXPIRATION_PERIOD="864000" # How long until a pending proposal expires (10 days) # TAIKO's PARAMETERS