diff --git a/script/releases/v1.10.0-rewards-v2.2/1-deployRewardsCoordinatorImpl.s.sol b/script/releases/v1.10.0-rewards-v2.2/1-deployRewardsCoordinatorImpl.s.sol new file mode 100644 index 0000000000..92172cd1f2 --- /dev/null +++ b/script/releases/v1.10.0-rewards-v2.2/1-deployRewardsCoordinatorImpl.s.sol @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.12; + +import {EOADeployer} from "zeus-templates/templates/EOADeployer.sol"; +import "../Env.sol"; +import "../TestUtils.sol"; + +/** + * @title DeployRewardsCoordinatorImpl + * @notice Deploy new RewardsCoordinator implementation with Rewards v2.2 support. + * This adds support for: + * - Unique stake rewards submissions (rewards linear to allocated unique stake) + * - Total stake rewards submissions (rewards linear to total stake) + * - Updated MAX_REWARDS_DURATION to 730 days (63072000 seconds) + */ +contract DeployRewardsCoordinatorImpl is EOADeployer { + using Env for *; + using TestUtils for *; + + /// forgefmt: disable-next-item + function _runAsEOA() internal override { + // Only execute on source chains with version 1.9.0 + if (!(Env.isSourceChain() && Env._strEq(Env.envVersion(), "1.9.0"))) { + return; + } + + vm.startBroadcast(); + + // Update the MAX_REWARDS_DURATION environment variable before deployment + // 63072000s = 730 days = 2 years + zUpdateUint32("REWARDS_COORDINATOR_MAX_REWARDS_DURATION", 63072000); + + // Deploy RewardsCoordinator implementation with the updated MAX_REWARDS_DURATION + deployImpl({ + name: type(RewardsCoordinator).name, + deployedTo: address( + new RewardsCoordinator( + IRewardsCoordinatorTypes.RewardsCoordinatorConstructorParams({ + delegationManager: Env.proxy.delegationManager(), + strategyManager: Env.proxy.strategyManager(), + allocationManager: Env.proxy.allocationManager(), + pauserRegistry: Env.impl.pauserRegistry(), + permissionController: Env.proxy.permissionController(), + CALCULATION_INTERVAL_SECONDS: Env.CALCULATION_INTERVAL_SECONDS(), + MAX_REWARDS_DURATION: Env.MAX_REWARDS_DURATION(), // Using updated env value + MAX_RETROACTIVE_LENGTH: Env.MAX_RETROACTIVE_LENGTH(), + MAX_FUTURE_LENGTH: Env.MAX_FUTURE_LENGTH(), + GENESIS_REWARDS_TIMESTAMP: Env.GENESIS_REWARDS_TIMESTAMP() + }) + ) + ) + }); + + vm.stopBroadcast(); + } + + function testScript() public virtual { + if (!(Env.isSourceChain() && Env._strEq(Env.envVersion(), "1.9.0"))) { + return; + } + + // Deploy the new RewardsCoordinator implementation + runAsEOA(); + + _validateNewImplAddress(); + _validateProxyAdmin(); + _validateImplConstructor(); + _validateZeusEnvUpdated(); + _validateImplInitialized(); + _validateNewFunctionality(); + _validateStorageLayout(); + } + + /// @dev Validate that the new RewardsCoordinator impl address is distinct from the current one + function _validateNewImplAddress() internal view { + address currentImpl = TestUtils._getProxyImpl(address(Env.proxy.rewardsCoordinator())); + address newImpl = address(Env.impl.rewardsCoordinator()); + + assertFalse(currentImpl == newImpl, "RewardsCoordinator impl should be different from current implementation"); + } + + /// @dev Validate that the RewardsCoordinator proxy is still owned by the correct ProxyAdmin + function _validateProxyAdmin() internal view { + address pa = Env.proxyAdmin(); + + assertTrue( + TestUtils._getProxyAdmin(address(Env.proxy.rewardsCoordinator())) == pa, + "RewardsCoordinator proxyAdmin incorrect" + ); + } + + /// @dev Validate the immutables set in the new RewardsCoordinator implementation constructor + function _validateImplConstructor() internal view { + RewardsCoordinator rewardsCoordinatorImpl = Env.impl.rewardsCoordinator(); + + // Validate core dependencies + assertTrue( + address(rewardsCoordinatorImpl.delegationManager()) == address(Env.proxy.delegationManager()), + "RewardsCoordinator delegationManager mismatch" + ); + assertTrue( + address(rewardsCoordinatorImpl.strategyManager()) == address(Env.proxy.strategyManager()), + "RewardsCoordinator strategyManager mismatch" + ); + assertTrue( + address(rewardsCoordinatorImpl.allocationManager()) == address(Env.proxy.allocationManager()), + "RewardsCoordinator allocationManager mismatch" + ); + assertTrue( + address(rewardsCoordinatorImpl.pauserRegistry()) == address(Env.impl.pauserRegistry()), + "RewardsCoordinator pauserRegistry mismatch" + ); + assertTrue( + address(rewardsCoordinatorImpl.permissionController()) == address(Env.proxy.permissionController()), + "RewardsCoordinator permissionController mismatch" + ); + + // Validate reward parameters + assertEq( + rewardsCoordinatorImpl.CALCULATION_INTERVAL_SECONDS(), + Env.CALCULATION_INTERVAL_SECONDS(), + "CALCULATION_INTERVAL_SECONDS mismatch" + ); + assertEq( + rewardsCoordinatorImpl.MAX_REWARDS_DURATION(), + 63_072_000, + "MAX_REWARDS_DURATION should be updated to 730 days (63072000 seconds)" + ); + assertEq( + rewardsCoordinatorImpl.MAX_RETROACTIVE_LENGTH(), + Env.MAX_RETROACTIVE_LENGTH(), + "MAX_RETROACTIVE_LENGTH mismatch" + ); + assertEq(rewardsCoordinatorImpl.MAX_FUTURE_LENGTH(), Env.MAX_FUTURE_LENGTH(), "MAX_FUTURE_LENGTH mismatch"); + assertEq( + rewardsCoordinatorImpl.GENESIS_REWARDS_TIMESTAMP(), + Env.GENESIS_REWARDS_TIMESTAMP(), + "GENESIS_REWARDS_TIMESTAMP mismatch" + ); + } + + /// @dev Validate that the zeus environment variable has been updated correctly + function _validateZeusEnvUpdated() internal view { + RewardsCoordinator rewardsCoordinatorImpl = Env.impl.rewardsCoordinator(); + + // Validate that the zeus env MAX_REWARDS_DURATION matches what was deployed + assertEq( + rewardsCoordinatorImpl.MAX_REWARDS_DURATION(), + Env.MAX_REWARDS_DURATION(), + "Deployed MAX_REWARDS_DURATION should match zeus env value" + ); + + // Also validate it equals the expected value + assertEq( + Env.MAX_REWARDS_DURATION(), + 63_072_000, + "Zeus env MAX_REWARDS_DURATION should be updated to 730 days (63072000 seconds)" + ); + } + + /// @dev Validate that the new implementation cannot be initialized (should revert) + function _validateImplInitialized() internal { + bytes memory errInit = "Initializable: contract is already initialized"; + + RewardsCoordinator rewardsCoordinatorImpl = Env.impl.rewardsCoordinator(); + + vm.expectRevert(errInit); + rewardsCoordinatorImpl.initialize( + address(0), // initialOwner + 0, // initialPausedStatus + address(0), // rewardsUpdater + 0, // activationDelay + 0 // defaultSplitBips + ); + } + + /// @dev Validate new Rewards v2.2 functionality + function _validateNewFunctionality() internal view { + RewardsCoordinator rewardsCoordinatorImpl = Env.impl.rewardsCoordinator(); + + // The new functions exist (this will fail to compile if they don't exist) + // Just checking that the contract has the expected interface + bytes4 createUniqueStakeSelector = rewardsCoordinatorImpl.createUniqueStakeRewardsSubmission.selector; + bytes4 createTotalStakeSelector = rewardsCoordinatorImpl.createTotalStakeRewardsSubmission.selector; + + // Verify the selectors are non-zero (functions exist) + assertTrue(createUniqueStakeSelector != bytes4(0), "createUniqueStakeRewardsSubmission function should exist"); + assertTrue(createTotalStakeSelector != bytes4(0), "createTotalStakeRewardsSubmission function should exist"); + } + + /// @dev Validate storage layout changes + function _validateStorageLayout() internal view { + // The storage gap was reduced from 35 to 33 slots to accommodate the new mappings: + // - isUniqueStakeRewardsSubmissionHash (1 slot) + // - isTotalStakeRewardsSubmissionHash (1 slot) + // This validation ensures the contract is compiled with the expected storage layout + + // We can't directly access the storage gap, but we can ensure the contract + // compiles and deploys successfully, which validates the storage layout is correct + RewardsCoordinator rewardsCoordinatorImpl = Env.impl.rewardsCoordinator(); + + // Verify we can access the existing public mappings + // This validates that storage layout hasn't been corrupted + + // Check that we can call view functions that access storage + address testAvs = address(0x1234); + bytes32 testHash = keccak256("test"); + + // These calls should not revert, validating storage is accessible + bool isAVS = rewardsCoordinatorImpl.isAVSRewardsSubmissionHash(testAvs, testHash); + bool isOperatorDirectedAVS = + rewardsCoordinatorImpl.isOperatorDirectedAVSRewardsSubmissionHash(testAvs, testHash); + bool isOperatorDirectedOperatorSet = + rewardsCoordinatorImpl.isOperatorDirectedOperatorSetRewardsSubmissionHash(testAvs, testHash); + bool isUniqueStake = rewardsCoordinatorImpl.isUniqueStakeRewardsSubmissionHash(testAvs, testHash); + bool isTotalStake = rewardsCoordinatorImpl.isTotalStakeRewardsSubmissionHash(testAvs, testHash); + + // All should be false for a random hash + assertFalse(isAVS, "Random hash should not be a rewards submission"); + assertFalse(isOperatorDirectedAVS, "Random hash should not be operator directed"); + assertFalse(isOperatorDirectedOperatorSet, "Random hash should not be operator set"); + assertFalse(isUniqueStake, "Random hash should not be unique stake"); + assertFalse(isTotalStake, "Random hash should not be total stake"); + } +} diff --git a/script/releases/v1.10.0-rewards-v2.2/2-queueRewardsCoordinatorUpgrade.s.sol b/script/releases/v1.10.0-rewards-v2.2/2-queueRewardsCoordinatorUpgrade.s.sol new file mode 100644 index 0000000000..74ebf363ac --- /dev/null +++ b/script/releases/v1.10.0-rewards-v2.2/2-queueRewardsCoordinatorUpgrade.s.sol @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.12; + +import {DeployRewardsCoordinatorImpl} from "./1-deployRewardsCoordinatorImpl.s.sol"; +import "../Env.sol"; +import "../TestUtils.sol"; + +import {MultisigBuilder} from "zeus-templates/templates/MultisigBuilder.sol"; +import {MultisigCall, Encode} from "zeus-templates/utils/Encode.sol"; + +import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol"; + +/** + * @title QueueRewardsCoordinatorUpgrade + * @notice Queue the RewardsCoordinator upgrade transaction in the Timelock via the Operations Multisig. + * This queues the upgrade to add Rewards v2.2 support: + * - Unique stake rewards (linear to allocated unique stake) + * - Total stake rewards (linear to total stake) + * - Updated MAX_REWARDS_DURATION to 730 days (63072000 seconds) + */ +contract QueueRewardsCoordinatorUpgrade is MultisigBuilder, DeployRewardsCoordinatorImpl { + using Env for *; + using Encode for *; + using TestUtils for *; + + function _runAsMultisig() internal virtual override prank(Env.opsMultisig()) { + if (!(Env.isSourceChain() && Env._strEq(Env.envVersion(), "1.9.0"))) { + return; + } + + bytes memory calldata_to_executor = _getCalldataToExecutor(); + + TimelockController timelock = Env.timelockController(); + timelock.schedule({ + target: Env.executorMultisig(), + value: 0, + data: calldata_to_executor, + predecessor: 0, + salt: 0, + delay: timelock.getMinDelay() + }); + } + + /// @dev Get the calldata to be sent from the timelock to the executor + function _getCalldataToExecutor() internal returns (bytes memory) { + /// forgefmt: disable-next-item + MultisigCall[] storage executorCalls = Encode.newMultisigCalls().append({ + to: Env.proxyAdmin(), + data: Encode.proxyAdmin.upgrade({ + proxy: address(Env.proxy.rewardsCoordinator()), + impl: address(Env.impl.rewardsCoordinator()) + }) + }); + + return Encode.gnosisSafe.execTransaction({ + from: address(Env.timelockController()), + to: Env.multiSendCallOnly(), + op: Encode.Operation.DelegateCall, + data: Encode.multiSend(executorCalls) + }); + } + + function testScript() public virtual override { + if (!(Env.isSourceChain() && Env._strEq(Env.envVersion(), "1.9.0"))) { + return; + } + + // 1 - Deploy. The new RewardsCoordinator implementation has been deployed + runAsEOA(); + + TimelockController timelock = Env.timelockController(); + bytes memory calldata_to_executor = _getCalldataToExecutor(); + bytes32 txHash = timelock.hashOperation({ + target: Env.executorMultisig(), + value: 0, + data: calldata_to_executor, + predecessor: 0, + salt: 0 + }); + + // Ensure transaction is not already queued + assertFalse(timelock.isOperationPending(txHash), "Transaction should not be queued yet"); + assertFalse(timelock.isOperationReady(txHash), "Transaction should not be ready"); + assertFalse(timelock.isOperationDone(txHash), "Transaction should not be complete"); + + // 2 - Queue the transaction + _runAsMultisig(); + _unsafeResetHasPranked(); // reset hasPranked so we can use it again + + // Verify transaction is queued + assertTrue(timelock.isOperationPending(txHash), "Transaction should be queued"); + assertFalse(timelock.isOperationReady(txHash), "Transaction should NOT be ready immediately"); + assertFalse(timelock.isOperationDone(txHash), "Transaction should NOT be complete"); + + // Validate that timelock delay is properly configured + uint256 minDelay = timelock.getMinDelay(); + assertTrue(minDelay > 0, "Timelock delay should be greater than 0"); + + // Validate proxy state before upgrade + _validatePreUpgradeState(); + } + + /// @dev Validate the state before the upgrade + function _validatePreUpgradeState() internal view { + RewardsCoordinator rewardsCoordinator = Env.proxy.rewardsCoordinator(); + + // Validate current implementation is different from new implementation + address currentImpl = TestUtils._getProxyImpl(address(rewardsCoordinator)); + address newImpl = address(Env.impl.rewardsCoordinator()); + assertTrue(currentImpl != newImpl, "Current and new implementations should be different"); + + // Validate current MAX_REWARDS_DURATION is different from new value + // Note: We access this through the proxy, which still points to the old implementation + uint32 currentMaxRewardsDuration = rewardsCoordinator.MAX_REWARDS_DURATION(); + assertTrue(currentMaxRewardsDuration != 63_072_000, "Current MAX_REWARDS_DURATION should not be 730 days yet"); + + // Validate that we're upgrading from the correct version + // We can't directly call them since they don't exist, but we can verify the upgrade is needed + // by checking that we're indeed on the right version + assertEq(Env.envVersion(), "1.9.0", "Should be on version 1.9.0 before upgrade"); + } +} diff --git a/script/releases/v1.10.0-rewards-v2.2/3-executeRewardsCoordinatorUpgrade.s.sol b/script/releases/v1.10.0-rewards-v2.2/3-executeRewardsCoordinatorUpgrade.s.sol new file mode 100644 index 0000000000..1a5724600d --- /dev/null +++ b/script/releases/v1.10.0-rewards-v2.2/3-executeRewardsCoordinatorUpgrade.s.sol @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.12; + +import "../Env.sol"; +import "../TestUtils.sol"; +import {QueueRewardsCoordinatorUpgrade} from "./2-queueRewardsCoordinatorUpgrade.s.sol"; +import {Encode} from "zeus-templates/utils/Encode.sol"; + +/** + * @title ExecuteRewardsCoordinatorUpgrade + * @notice Execute the queued RewardsCoordinator upgrade after the timelock delay. + * This completes the upgrade to add Rewards v2.2 support: + * - Unique stake rewards (linear to allocated unique stake) + * - Total stake rewards (linear to total stake) + * - Updated MAX_REWARDS_DURATION to 730 days (63072000 seconds) + */ +contract ExecuteRewardsCoordinatorUpgrade is QueueRewardsCoordinatorUpgrade { + using Env for *; + using Encode for *; + using TestUtils for *; + + function _runAsMultisig() internal override prank(Env.protocolCouncilMultisig()) { + if (!(Env.isSourceChain() && Env._strEq(Env.envVersion(), "1.9.0"))) { + return; + } + + bytes memory calldata_to_executor = _getCalldataToExecutor(); + TimelockController timelock = Env.timelockController(); + + timelock.execute({ + target: Env.executorMultisig(), + value: 0, + payload: calldata_to_executor, + predecessor: 0, + salt: 0 + }); + } + + function testScript() public virtual override { + if (!(Env.isSourceChain() && Env._strEq(Env.envVersion(), "1.9.0"))) { + return; + } + + // 1 - Deploy. The new RewardsCoordinator implementation has been deployed + runAsEOA(); + + TimelockController timelock = Env.timelockController(); + bytes memory calldata_to_executor = _getCalldataToExecutor(); + bytes32 txHash = timelock.hashOperation({ + target: Env.executorMultisig(), + value: 0, + data: calldata_to_executor, + predecessor: 0, + salt: 0 + }); + + // 2 - Queue. Check that the operation IS ready + QueueRewardsCoordinatorUpgrade._runAsMultisig(); + _unsafeResetHasPranked(); // reset hasPranked so we can use it again + + assertTrue(timelock.isOperationPending(txHash), "Transaction should be queued"); + assertFalse(timelock.isOperationReady(txHash), "Transaction should NOT be ready immediately"); + assertFalse(timelock.isOperationDone(txHash), "Transaction should NOT be complete"); + + // 3 - Warp past the timelock delay + vm.warp(block.timestamp + timelock.getMinDelay()); + assertTrue(timelock.isOperationReady(txHash), "Transaction should be ready for execution"); + + // 4 - Execute the upgrade + execute(); + assertTrue(timelock.isOperationDone(txHash), "v1.10.0 RewardsCoordinator upgrade should be complete"); + + // 5 - Validate the upgrade was successful + _validateUpgradeComplete(); + _validateProxyAdmin(); + _validateProxyConstructor(); + _validateProxyInitialized(); + _validateNewFunctionalityThroughProxy(); + } + + /// @dev Validate that the RewardsCoordinator proxy now points to the new implementation + function _validateUpgradeComplete() internal view { + address currentImpl = TestUtils._getProxyImpl(address(Env.proxy.rewardsCoordinator())); + address expectedImpl = address(Env.impl.rewardsCoordinator()); + + assertTrue(currentImpl == expectedImpl, "RewardsCoordinator proxy should point to new implementation"); + } + + /// @dev Validate the proxy's constructor values through the proxy + function _validateProxyConstructor() internal view { + RewardsCoordinator rewardsCoordinator = Env.proxy.rewardsCoordinator(); + + // Validate core dependencies + assertTrue( + address(rewardsCoordinator.delegationManager()) == address(Env.proxy.delegationManager()), + "RewardsCoordinator delegationManager mismatch" + ); + assertTrue( + address(rewardsCoordinator.strategyManager()) == address(Env.proxy.strategyManager()), + "RewardsCoordinator strategyManager mismatch" + ); + assertTrue( + address(rewardsCoordinator.allocationManager()) == address(Env.proxy.allocationManager()), + "RewardsCoordinator allocationManager mismatch" + ); + assertTrue( + address(rewardsCoordinator.pauserRegistry()) == address(Env.impl.pauserRegistry()), + "RewardsCoordinator pauserRegistry mismatch" + ); + assertTrue( + address(rewardsCoordinator.permissionController()) == address(Env.proxy.permissionController()), + "RewardsCoordinator permissionController mismatch" + ); + + // Validate reward parameters + assertEq( + rewardsCoordinator.CALCULATION_INTERVAL_SECONDS(), + Env.CALCULATION_INTERVAL_SECONDS(), + "CALCULATION_INTERVAL_SECONDS mismatch" + ); + + // Validate the updated MAX_REWARDS_DURATION + assertEq( + rewardsCoordinator.MAX_REWARDS_DURATION(), + 63_072_000, + "MAX_REWARDS_DURATION should be updated to 730 days (63072000 seconds)" + ); + + assertEq( + rewardsCoordinator.MAX_RETROACTIVE_LENGTH(), Env.MAX_RETROACTIVE_LENGTH(), "MAX_RETROACTIVE_LENGTH mismatch" + ); + assertEq(rewardsCoordinator.MAX_FUTURE_LENGTH(), Env.MAX_FUTURE_LENGTH(), "MAX_FUTURE_LENGTH mismatch"); + + assertEq( + rewardsCoordinator.GENESIS_REWARDS_TIMESTAMP(), + Env.GENESIS_REWARDS_TIMESTAMP(), + "GENESIS_REWARDS_TIMESTAMP mismatch" + ); + } + + /// @dev Validate that the proxy is still initialized and cannot be re-initialized + function _validateProxyInitialized() internal { + RewardsCoordinator rewardsCoordinator = Env.proxy.rewardsCoordinator(); + + // Validate the existing initializable state variables are still set + assertTrue(rewardsCoordinator.paused() == Env.REWARDS_PAUSE_STATUS(), "Paused status should still be set"); + assertTrue(rewardsCoordinator.owner() == Env.opsMultisig(), "Owner should still be set"); + assertTrue(rewardsCoordinator.rewardsUpdater() == Env.REWARDS_UPDATER(), "RewardsUpdater should still be set"); + assertTrue( + rewardsCoordinator.activationDelay() == Env.ACTIVATION_DELAY(), "Activation delay should still be set" + ); + assertTrue( + rewardsCoordinator.defaultOperatorSplitBips() == Env.DEFAULT_SPLIT_BIPS(), + "Default split bips should still be set" + ); + + // Attempt to re-initialize should fail + bytes memory errInit = "Initializable: contract is already initialized"; + vm.expectRevert(errInit); + rewardsCoordinator.initialize( + address(0x1234), // initialOwner + 0, // initialPausedStatus + address(0x9ABC), // rewardsUpdater + 0, // activationDelay + 0 // defaultSplitBips + ); + } + + /// @dev Validate new Rewards v2.2 functionality through the proxy + function _validateNewFunctionalityThroughProxy() internal view { + RewardsCoordinator rewardsCoordinator = Env.proxy.rewardsCoordinator(); + + // The new functions should be accessible through the proxy + bytes4 createUniqueStakeSelector = rewardsCoordinator.createUniqueStakeRewardsSubmission.selector; + bytes4 createTotalStakeSelector = rewardsCoordinator.createTotalStakeRewardsSubmission.selector; + + // Verify the selectors are non-zero (functions exist) + assertTrue( + createUniqueStakeSelector != bytes4(0), "createUniqueStakeRewardsSubmission function should exist on proxy" + ); + assertTrue( + createTotalStakeSelector != bytes4(0), "createTotalStakeRewardsSubmission function should exist on proxy" + ); + + // Test that we can access the new storage mappings + address testAvs = address(0xDEAD); + bytes32 testHash = keccak256("test_rewards_v2.2"); + + // These should all return false for test values, but accessing them validates the storage layout + bool isUniqueStake = rewardsCoordinator.isUniqueStakeRewardsSubmissionHash(testAvs, testHash); + bool isTotalStake = rewardsCoordinator.isTotalStakeRewardsSubmissionHash(testAvs, testHash); + + assertFalse(isUniqueStake, "Test hash should not be a unique stake submission"); + assertFalse(isTotalStake, "Test hash should not be a total stake submission"); + } +} diff --git a/script/releases/v1.10.0-rewards-v2.2/upgrade.json b/script/releases/v1.10.0-rewards-v2.2/upgrade.json new file mode 100644 index 0000000000..05d1f68665 --- /dev/null +++ b/script/releases/v1.10.0-rewards-v2.2/upgrade.json @@ -0,0 +1,19 @@ +{ + "name": "rewards-v2.2-v1.10.0", + "from": "1.9.0", + "to": "1.10.0", + "phases": [ + { + "type": "eoa", + "filename": "1-deployRewardsCoordinatorImpl.s.sol" + }, + { + "type": "multisig", + "filename": "2-queueRewardsCoordinatorUpgrade.s.sol" + }, + { + "type": "multisig", + "filename": "3-executeRewardsCoordinatorUpgrade.s.sol" + } + ] +} \ No newline at end of file diff --git a/script/releases/v1.9.0-slashing-ux-destination/1-deployProtocolRegistryProxy.s.sol b/script/releases/v1.9.0-slashing-ux-destination/1-deployProtocolRegistryProxy.s.sol index 4fb0ffb6e8..4fa9743fb7 100644 --- a/script/releases/v1.9.0-slashing-ux-destination/1-deployProtocolRegistryProxy.s.sol +++ b/script/releases/v1.9.0-slashing-ux-destination/1-deployProtocolRegistryProxy.s.sol @@ -15,6 +15,11 @@ contract DeployProtocolRegistryProxy is MultisigBuilder { /// forgefmt: disable-next-item function _runAsMultisig() internal virtual override { + // Only execute on version 1.8.1 + if (!Env._strEq(Env.envVersion(), "1.8.1")) { + return; + } + // We don't use the prank modifier here, since we have to write to the env _startPrank(Env.multichainDeployerMultisig()); @@ -33,7 +38,7 @@ contract DeployProtocolRegistryProxy is MultisigBuilder { } function testScript() public virtual { - if (Env.isCoreProtocolDeployed()) { + if (Env.isCoreProtocolDeployed() || !Env._strEq(Env.envVersion(), "1.8.1")) { return; } diff --git a/script/releases/v1.9.0-slashing-ux-destination/2-deployProtocolRegistryImpl.s.sol b/script/releases/v1.9.0-slashing-ux-destination/2-deployProtocolRegistryImpl.s.sol index 1aa43c1d54..e41221c3b3 100644 --- a/script/releases/v1.9.0-slashing-ux-destination/2-deployProtocolRegistryImpl.s.sol +++ b/script/releases/v1.9.0-slashing-ux-destination/2-deployProtocolRegistryImpl.s.sol @@ -14,6 +14,11 @@ contract DeployProtocolRegistryImpl is DeployProtocolRegistryProxy, CoreContract using Env for *; function _runAsEOA() internal virtual override { + // Only execute on version 1.8.1 + if (!Env._strEq(Env.envVersion(), "1.8.1")) { + return; + } + vm.startBroadcast(); // Deploy Protocol Registry implementation @@ -23,7 +28,7 @@ contract DeployProtocolRegistryImpl is DeployProtocolRegistryProxy, CoreContract } function testScript() public virtual override { - if (Env.isCoreProtocolDeployed()) { + if (Env.isCoreProtocolDeployed() || !Env._strEq(Env.envVersion(), "1.8.1")) { return; } diff --git a/script/releases/v1.9.0-slashing-ux-destination/3-upgradeProtocolRegistry.s.sol b/script/releases/v1.9.0-slashing-ux-destination/3-upgradeProtocolRegistry.s.sol index fe82c3ddab..c88bb6eed6 100644 --- a/script/releases/v1.9.0-slashing-ux-destination/3-upgradeProtocolRegistry.s.sol +++ b/script/releases/v1.9.0-slashing-ux-destination/3-upgradeProtocolRegistry.s.sol @@ -17,6 +17,11 @@ contract UpgradeProtocolRegistry is DeployProtocolRegistryImpl { /// forgefmt: disable-next-item function _runAsMultisig() internal virtual override prank(Env.multichainDeployerMultisig()) { + // Only execute on version 1.8.1 + if (!Env._strEq(Env.envVersion(), "1.8.1")) { + return; + } + // Upgrade the proxies to point to the actual implementations ITransparentUpgradeableProxy protocolRegistryProxy = ITransparentUpgradeableProxy(payable(address(Env.proxy.protocolRegistry()))); @@ -27,7 +32,7 @@ contract UpgradeProtocolRegistry is DeployProtocolRegistryImpl { } function testScript() public virtual override { - if (Env.isCoreProtocolDeployed()) { + if (Env.isCoreProtocolDeployed() || !Env._strEq(Env.envVersion(), "1.8.1")) { return; } // 1. Deploy the Protocol Registry Proxy diff --git a/script/releases/v1.9.0-slashing-ux-destination/4-deployCoreContracts.s.sol b/script/releases/v1.9.0-slashing-ux-destination/4-deployCoreContracts.s.sol index ee280251f7..e5389e7687 100644 --- a/script/releases/v1.9.0-slashing-ux-destination/4-deployCoreContracts.s.sol +++ b/script/releases/v1.9.0-slashing-ux-destination/4-deployCoreContracts.s.sol @@ -28,6 +28,11 @@ contract DeployCoreContracts is UpgradeProtocolRegistry { using Env for *; function _runAsEOA() internal override { + // Only execute on version 1.8.1 + if (!Env._strEq(Env.envVersion(), "1.8.1")) { + return; + } + vm.startBroadcast(); /** @@ -47,7 +52,7 @@ contract DeployCoreContracts is UpgradeProtocolRegistry { } function testScript() public virtual override { - if (Env.isCoreProtocolDeployed()) { + if (Env.isCoreProtocolDeployed() || !Env._strEq(Env.envVersion(), "1.8.1")) { return; } diff --git a/script/releases/v1.9.0-slashing-ux-destination/5-queueUpgrade.s.sol b/script/releases/v1.9.0-slashing-ux-destination/5-queueUpgrade.s.sol index 5ec1831200..2ced60438c 100644 --- a/script/releases/v1.9.0-slashing-ux-destination/5-queueUpgrade.s.sol +++ b/script/releases/v1.9.0-slashing-ux-destination/5-queueUpgrade.s.sol @@ -18,6 +18,11 @@ contract QueueUpgrade is DeployCoreContracts { using CoreUpgradeQueueBuilder for MultisigCall[]; function _runAsMultisig() internal virtual override prank(Env.opsMultisig()) { + // Only execute on version 1.8.1 + if (!Env._strEq(Env.envVersion(), "1.8.1")) { + return; + } + bytes memory calldata_to_executor = _getCalldataToExecutor(); TimelockController timelock = Env.timelockController(); @@ -113,7 +118,7 @@ contract QueueUpgrade is DeployCoreContracts { } function testScript() public virtual override { - if (Env.isCoreProtocolDeployed()) { + if (Env.isCoreProtocolDeployed() || !Env._strEq(Env.envVersion(), "1.8.1")) { return; } diff --git a/script/releases/v1.9.0-slashing-ux-destination/6-completeUpgrade.s.sol b/script/releases/v1.9.0-slashing-ux-destination/6-completeUpgrade.s.sol index af04bda987..d198e4818d 100644 --- a/script/releases/v1.9.0-slashing-ux-destination/6-completeUpgrade.s.sol +++ b/script/releases/v1.9.0-slashing-ux-destination/6-completeUpgrade.s.sol @@ -12,6 +12,11 @@ contract ExecuteUpgrade is QueueUpgrade { using Env for *; function _runAsMultisig() internal virtual override prank(Env.protocolCouncilMultisig()) { + // Only execute on version 1.8.1 + if (!Env._strEq(Env.envVersion(), "1.8.1")) { + return; + } + bytes memory calldata_to_executor = _getCalldataToExecutor(); TimelockController timelock = Env.timelockController(); @@ -25,7 +30,7 @@ contract ExecuteUpgrade is QueueUpgrade { } function testScript() public virtual override { - if (Env.isCoreProtocolDeployed()) { + if (Env.isCoreProtocolDeployed() || !Env._strEq(Env.envVersion(), "1.8.1")) { return; } diff --git a/script/releases/v1.9.0-slashing-ux/1-deployProtocolRegistryProxy.s.sol b/script/releases/v1.9.0-slashing-ux/1-deployProtocolRegistryProxy.s.sol index 5a671f3542..68088534d9 100644 --- a/script/releases/v1.9.0-slashing-ux/1-deployProtocolRegistryProxy.s.sol +++ b/script/releases/v1.9.0-slashing-ux/1-deployProtocolRegistryProxy.s.sol @@ -15,6 +15,11 @@ contract DeployProtocolRegistryProxy is MultisigBuilder { /// forgefmt: disable-next-item function _runAsMultisig() internal virtual override { + // Only execute on version 1.8.1 + if (!Env._strEq(Env.envVersion(), "1.8.1")) { + return; + } + // We don't use the prank modifier here, since we have to write to the env _startPrank(Env.multichainDeployerMultisig()); @@ -33,7 +38,7 @@ contract DeployProtocolRegistryProxy is MultisigBuilder { } function testScript() public virtual { - if (!Env.isCoreProtocolDeployed()) { + if (!Env.isCoreProtocolDeployed() || !Env._strEq(Env.envVersion(), "1.8.1")) { return; } execute(); diff --git a/script/releases/v1.9.0-slashing-ux/2-deployProtocolRegistryImpl.s.sol b/script/releases/v1.9.0-slashing-ux/2-deployProtocolRegistryImpl.s.sol index 2c0480ade6..f9ef003402 100644 --- a/script/releases/v1.9.0-slashing-ux/2-deployProtocolRegistryImpl.s.sol +++ b/script/releases/v1.9.0-slashing-ux/2-deployProtocolRegistryImpl.s.sol @@ -14,6 +14,11 @@ contract DeployProtocolRegistryImpl is DeployProtocolRegistryProxy, CoreContract using Env for *; function _runAsEOA() internal virtual override { + // Only execute on version 1.8.1 + if (!Env._strEq(Env.envVersion(), "1.8.1")) { + return; + } + vm.startBroadcast(); // Deploy Protocol Registry implementation @@ -23,7 +28,7 @@ contract DeployProtocolRegistryImpl is DeployProtocolRegistryProxy, CoreContract } function testScript() public virtual override { - if (!Env.isCoreProtocolDeployed()) { + if (!Env.isCoreProtocolDeployed() || !Env._strEq(Env.envVersion(), "1.8.1")) { return; } // 1. Deploy Protocol Registry Proxy diff --git a/script/releases/v1.9.0-slashing-ux/3-upgradeProtocolRegistry.s.sol b/script/releases/v1.9.0-slashing-ux/3-upgradeProtocolRegistry.s.sol index 06fa8aa8de..343ac75c2c 100644 --- a/script/releases/v1.9.0-slashing-ux/3-upgradeProtocolRegistry.s.sol +++ b/script/releases/v1.9.0-slashing-ux/3-upgradeProtocolRegistry.s.sol @@ -17,6 +17,11 @@ contract UpgradeProtocolRegistry is DeployProtocolRegistryImpl { /// forgefmt: disable-next-item function _runAsMultisig() internal virtual override prank(Env.multichainDeployerMultisig()) { + // Only execute on version 1.8.1 + if (!Env._strEq(Env.envVersion(), "1.8.1")) { + return; + } + // Upgrade the proxies to point to the actual implementations ITransparentUpgradeableProxy protocolRegistryProxy = ITransparentUpgradeableProxy(payable(address(Env.proxy.protocolRegistry()))); @@ -27,7 +32,7 @@ contract UpgradeProtocolRegistry is DeployProtocolRegistryImpl { } function testScript() public virtual override { - if (!Env.isCoreProtocolDeployed()) { + if (!Env.isCoreProtocolDeployed() || !Env._strEq(Env.envVersion(), "1.8.1")) { return; } // 1. Deploy the Protocol Registry Proxy diff --git a/script/releases/v1.9.0-slashing-ux/4-deployCoreContracts.s.sol b/script/releases/v1.9.0-slashing-ux/4-deployCoreContracts.s.sol index 853e7f9d1a..2e8191dc35 100644 --- a/script/releases/v1.9.0-slashing-ux/4-deployCoreContracts.s.sol +++ b/script/releases/v1.9.0-slashing-ux/4-deployCoreContracts.s.sol @@ -46,6 +46,11 @@ contract DeployCoreContracts is UpgradeProtocolRegistry { using Env for *; function _runAsEOA() internal override { + // Only execute on version 1.8.1 + if (!Env._strEq(Env.envVersion(), "1.8.1")) { + return; + } + vm.startBroadcast(); /** @@ -97,7 +102,7 @@ contract DeployCoreContracts is UpgradeProtocolRegistry { } function testScript() public virtual override { - if (!Env.isCoreProtocolDeployed()) { + if (!Env.isCoreProtocolDeployed() || !Env._strEq(Env.envVersion(), "1.8.1")) { return; } // Deploy protocol registry and initialize it diff --git a/script/releases/v1.9.0-slashing-ux/5-queueUpgrade.s.sol b/script/releases/v1.9.0-slashing-ux/5-queueUpgrade.s.sol index 9b105db45f..278b49441e 100644 --- a/script/releases/v1.9.0-slashing-ux/5-queueUpgrade.s.sol +++ b/script/releases/v1.9.0-slashing-ux/5-queueUpgrade.s.sol @@ -18,6 +18,11 @@ contract QueueUpgrade is DeployCoreContracts { using CoreUpgradeQueueBuilder for MultisigCall[]; function _runAsMultisig() internal virtual override prank(Env.opsMultisig()) { + // Only execute on version 1.8.1 + if (!Env._strEq(Env.envVersion(), "1.8.1")) { + return; + } + bytes memory calldata_to_executor = _getCalldataToExecutor(); TimelockController timelock = Env.timelockController(); @@ -234,7 +239,7 @@ contract QueueUpgrade is DeployCoreContracts { } function testScript() public virtual override { - if (!Env.isCoreProtocolDeployed()) { + if (!Env.isCoreProtocolDeployed() || !Env._strEq(Env.envVersion(), "1.8.1")) { return; } // Complete previous steps diff --git a/script/releases/v1.9.0-slashing-ux/6-completeUpgrade.s.sol b/script/releases/v1.9.0-slashing-ux/6-completeUpgrade.s.sol index 1cd3d9abde..9304d30ade 100644 --- a/script/releases/v1.9.0-slashing-ux/6-completeUpgrade.s.sol +++ b/script/releases/v1.9.0-slashing-ux/6-completeUpgrade.s.sol @@ -12,6 +12,11 @@ contract ExecuteUpgrade is QueueUpgrade { using Env for *; function _runAsMultisig() internal virtual override prank(Env.protocolCouncilMultisig()) { + // Only execute on version 1.8.1 + if (!Env._strEq(Env.envVersion(), "1.8.1")) { + return; + } + bytes memory calldata_to_executor = _getCalldataToExecutor(); TimelockController timelock = Env.timelockController(); @@ -25,7 +30,7 @@ contract ExecuteUpgrade is QueueUpgrade { } function testScript() public virtual override { - if (!Env.isCoreProtocolDeployed()) { + if (!Env.isCoreProtocolDeployed() || !Env._strEq(Env.envVersion(), "1.8.1")) { return; } // Complete previous steps