-
Notifications
You must be signed in to change notification settings - Fork 348
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: patch rewards v2 #940
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity ^0.8.12; | ||
|
||
import {EOADeployer} from "zeus-templates/templates/EOADeployer.sol"; | ||
import {RewardsCoordinator} from "src/contracts/core/RewardsCoordinator.sol"; | ||
import {IDelegationManager} from "src/contracts/interfaces/IDelegationManager.sol"; | ||
import {DelegationManager} from "src/contracts/core/DelegationManager.sol"; | ||
import {StrategyManager} from "src/contracts/core/StrategyManager.sol"; | ||
import {EigenLabsUpgrade} from "../EigenLabsUpgrade.s.sol"; | ||
import {Test, console} from "forge-std/Test.sol"; | ||
import {IPauserRegistry} from "src/contracts/interfaces/IPauserRegistry.sol"; | ||
|
||
contract Deploy is EOADeployer { | ||
using EigenLabsUpgrade for *; | ||
|
||
function _runAsEOA() internal override { | ||
zUpdateUint16(string("REWARDS_COORDINATOR_DEFAULT_OPERATOR_SPLIT_BIPS"), uint16(1000)); | ||
zUpdateUint32(string("REWARDS_COORDINATOR_CALCULATION_INTERVAL_SECONDS"), uint32(1 days)); | ||
|
||
vm.startBroadcast(); | ||
deploySingleton( | ||
address( | ||
new RewardsCoordinator( | ||
IDelegationManager(zDeployedProxy(type(DelegationManager).name)), | ||
StrategyManager(zDeployedProxy(type(StrategyManager).name)), | ||
zUint32("REWARDS_COORDINATOR_CALCULATION_INTERVAL_SECONDS"), | ||
zUint32("REWARDS_COORDINATOR_MAX_REWARDS_DURATION"), | ||
zUint32("REWARDS_COORDINATOR_MAX_RETROACTIVE_LENGTH"), | ||
zUint32("REWARDS_COORDINATOR_MAX_FUTURE_LENGTH"), | ||
zUint32("REWARDS_COORDINATOR_GENESIS_REWARDS_TIMESTAMP") | ||
) | ||
), | ||
this.impl(type(RewardsCoordinator).name) | ||
); | ||
|
||
vm.stopBroadcast(); | ||
} | ||
|
||
function testDeploy() public virtual { | ||
// Deploy RewardsCoordinator Implementation | ||
address oldImpl = zDeployedImpl(type(RewardsCoordinator).name); | ||
runAsEOA(); | ||
address newImpl = zDeployedImpl(type(RewardsCoordinator).name); | ||
assertTrue(oldImpl != newImpl, "impl should be different"); | ||
|
||
Deployment[] memory deploys = deploys(); | ||
|
||
// sanity check that zDeployedImpl is returning our deployment. | ||
assertEq(deploys[0].deployedTo, zDeployedImpl(type(RewardsCoordinator).name)); | ||
|
||
RewardsCoordinator rewardsCoordinatorImpl = RewardsCoordinator(zDeployedImpl(type(RewardsCoordinator).name)); | ||
|
||
address owner = this._operationsMultisig(); | ||
IPauserRegistry pauserRegistry = IPauserRegistry(this._pauserRegistry()); | ||
uint64 initPausedStatus = zUint64("REWARDS_COORDINATOR_INIT_PAUSED_STATUS"); | ||
address rewardsUpdater = zAddress("REWARDS_COORDINATOR_UPDATER"); | ||
uint32 activationDelay = zUint32("REWARDS_COORDINATOR_ACTIVATION_DELAY"); | ||
uint16 defaultOperatorSplitBips = zUint16("REWARDS_COORDINATOR_DEFAULT_OPERATOR_SPLIT_BIPS"); | ||
|
||
// Ensure that the implementation contract cannot be initialized. | ||
vm.expectRevert("Initializable: contract is already initialized"); | ||
rewardsCoordinatorImpl.initialize( | ||
owner, | ||
pauserRegistry, | ||
initPausedStatus, | ||
rewardsUpdater, | ||
activationDelay, | ||
defaultOperatorSplitBips | ||
); | ||
|
||
// Assert Immutables and State Variables set through initialize | ||
assertEq(rewardsCoordinatorImpl.owner(), address(0), "expected owner"); | ||
assertEq(address(rewardsCoordinatorImpl.pauserRegistry()), address(0), "expected pauserRegistry"); | ||
assertEq(address(rewardsCoordinatorImpl.rewardsUpdater()), address(0), "expected rewardsUpdater"); | ||
assertEq(rewardsCoordinatorImpl.activationDelay(), 0, "expected activationDelay"); | ||
assertEq(rewardsCoordinatorImpl.defaultOperatorSplitBips(), 0, "expected defaultOperatorSplitBips"); | ||
|
||
assertEq( | ||
address(rewardsCoordinatorImpl.delegationManager()), | ||
zDeployedProxy(type(DelegationManager).name), | ||
"expected delegationManager" | ||
); | ||
assertEq( | ||
address(rewardsCoordinatorImpl.strategyManager()), | ||
zDeployedProxy(type(StrategyManager).name), | ||
"expected strategyManager" | ||
); | ||
|
||
assertEq( | ||
rewardsCoordinatorImpl.CALCULATION_INTERVAL_SECONDS(), | ||
zUint32("REWARDS_COORDINATOR_CALCULATION_INTERVAL_SECONDS"), | ||
"expected REWARDS_COORDINATOR_CALCULATION_INTERVAL_SECONDS" | ||
); | ||
assertEq( | ||
rewardsCoordinatorImpl.CALCULATION_INTERVAL_SECONDS(), | ||
1 days, | ||
"expected REWARDS_COORDINATOR_CALCULATION_INTERVAL_SECONDS" | ||
); | ||
assertGt( | ||
rewardsCoordinatorImpl.CALCULATION_INTERVAL_SECONDS(), | ||
0, | ||
"expected non-zero REWARDS_COORDINATOR_CALCULATION_INTERVAL_SECONDS" | ||
); | ||
|
||
assertEq(rewardsCoordinatorImpl.MAX_REWARDS_DURATION(), zUint32("REWARDS_COORDINATOR_MAX_REWARDS_DURATION")); | ||
assertGt(rewardsCoordinatorImpl.MAX_REWARDS_DURATION(), 0); | ||
|
||
assertEq( | ||
rewardsCoordinatorImpl.MAX_RETROACTIVE_LENGTH(), | ||
zUint32("REWARDS_COORDINATOR_MAX_RETROACTIVE_LENGTH") | ||
); | ||
assertGt(rewardsCoordinatorImpl.MAX_RETROACTIVE_LENGTH(), 0); | ||
|
||
assertEq(rewardsCoordinatorImpl.MAX_FUTURE_LENGTH(), zUint32("REWARDS_COORDINATOR_MAX_FUTURE_LENGTH")); | ||
assertGt(rewardsCoordinatorImpl.MAX_FUTURE_LENGTH(), 0); | ||
|
||
assertEq( | ||
rewardsCoordinatorImpl.GENESIS_REWARDS_TIMESTAMP(), | ||
zUint32("REWARDS_COORDINATOR_GENESIS_REWARDS_TIMESTAMP") | ||
); | ||
assertGt(rewardsCoordinatorImpl.GENESIS_REWARDS_TIMESTAMP(), 0); | ||
|
||
assertEq(deploys.length, 1, "expected exactly 1 deployment"); | ||
assertEq( | ||
keccak256(bytes(deploys[0].name)), | ||
keccak256(bytes(this.impl(type(RewardsCoordinator).name))), | ||
"zeusTest: Deployment name is not RewardsCoordinator" | ||
); | ||
assertTrue(deploys[0].singleton == true, "zeusTest: RewardsCoordinator should be a singleton."); | ||
assertNotEq(deploys[0].deployedTo, address(0), "zeusTest: Should deploy to non-zero address."); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity ^0.8.12; | ||
|
||
import {MultisigCall, MultisigCallUtils, MultisigBuilder} from "zeus-templates/templates/MultisigBuilder.sol"; | ||
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; | ||
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; | ||
import {Deploy} from "./1-eoa.s.sol"; | ||
import {RewardsCoordinator} from "src/contracts/core/RewardsCoordinator.sol"; | ||
import {EigenLabsUpgrade} from "../EigenLabsUpgrade.s.sol"; | ||
import {IPauserRegistry} from "src/contracts/interfaces/IPauserRegistry.sol"; | ||
import {ITimelock} from "zeus-templates/interfaces/ITimelock.sol"; | ||
import {console} from "forge-std/console.sol"; | ||
import {EncGnosisSafe} from "zeus-templates/utils/EncGnosisSafe.sol"; | ||
import {MultisigCallUtils, MultisigCall} from "zeus-templates/utils/MultisigCallUtils.sol"; | ||
import {IMultiSend} from "zeus-templates/interfaces/IMultiSend.sol"; | ||
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol"; | ||
|
||
/** | ||
* Purpose: enqueue a multisig transaction which tells the ProxyAdmin to upgrade RewardsCoordinator. | ||
*/ | ||
contract Queue is MultisigBuilder, Deploy { | ||
using MultisigCallUtils for MultisigCall[]; | ||
using EigenLabsUpgrade for *; | ||
using EncGnosisSafe for *; | ||
using MultisigCallUtils for *; | ||
|
||
MultisigCall[] private _executorCalls; | ||
MultisigCall[] private _opsCalls; | ||
|
||
function options() internal virtual override view returns (MultisigOptions memory) { | ||
return MultisigOptions( | ||
this._operationsMultisig(), | ||
Operation.Call | ||
); | ||
} | ||
|
||
function _getMultisigTransactionCalldata() internal view returns (bytes memory) { | ||
ProxyAdmin pa = ProxyAdmin(this._proxyAdmin()); | ||
|
||
bytes memory proxyAdminCalldata = abi.encodeCall( | ||
pa.upgrade, | ||
( | ||
TransparentUpgradeableProxy(payable(zDeployedProxy(type(RewardsCoordinator).name))), | ||
zDeployedImpl(type(RewardsCoordinator).name) | ||
) | ||
); | ||
|
||
bytes memory executorMultisigCalldata = address(this._timelock()).calldataToExecTransaction( | ||
this._proxyAdmin(), | ||
proxyAdminCalldata, | ||
EncGnosisSafe.Operation.Call | ||
); | ||
|
||
return (executorMultisigCalldata); | ||
} | ||
|
||
function runAsMultisig() internal virtual override { | ||
bytes memory executorMultisigCalldata = _getMultisigTransactionCalldata(); | ||
|
||
TimelockController timelock = TimelockController(payable(this._timelock())); | ||
timelock.schedule( | ||
this._executorMultisig(), | ||
0 /* value */, | ||
executorMultisigCalldata, | ||
0 /* predecessor */, | ||
bytes32(0) /* salt */, | ||
timelock.getMinDelay() | ||
); | ||
} | ||
|
||
function testDeploy() public virtual override { | ||
runAsEOA(); | ||
|
||
execute(); | ||
TimelockController timelock = TimelockController(payable(this._timelock())); | ||
|
||
bytes memory multisigTxnData = _getMultisigTransactionCalldata(); | ||
bytes32 txHash = timelock.hashOperation(this._executorMultisig(), 0, multisigTxnData, 0, 0); | ||
|
||
assertEq(timelock.isOperationPending(txHash), true, "Transaction should be queued."); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity ^0.8.12; | ||
|
||
import {MultisigCall, MultisigCallUtils, MultisigBuilder} from "zeus-templates/templates/MultisigBuilder.sol"; | ||
import {SafeTx, SafeTxUtils} from "zeus-templates/utils/SafeTxUtils.sol"; | ||
import {Queue} from "./2-multisig.s.sol"; | ||
import {EigenLabsUpgrade} from "../EigenLabsUpgrade.s.sol"; | ||
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol"; | ||
import {RewardsCoordinator} from "src/contracts/core/RewardsCoordinator.sol"; | ||
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; | ||
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; | ||
import {IPauserRegistry} from "src/contracts/interfaces/IPauserRegistry.sol"; | ||
import {DelegationManager} from "src/contracts/core/DelegationManager.sol"; | ||
import {StrategyManager} from "src/contracts/core/StrategyManager.sol"; | ||
import {console} from "forge-std/console.sol"; | ||
|
||
contract Execute is Queue { | ||
using MultisigCallUtils for MultisigCall[]; | ||
using SafeTxUtils for SafeTx; | ||
using EigenLabsUpgrade for *; | ||
|
||
event Upgraded(address indexed implementation); | ||
|
||
function options() internal view override returns (MultisigOptions memory) { | ||
return MultisigOptions(this._protocolCouncilMultisig(), Operation.Call); | ||
} | ||
|
||
/** | ||
* @dev Overrides the previous _execute function to execute the queued transactions. | ||
*/ | ||
function runAsMultisig() internal override { | ||
bytes memory executorMultisigCalldata = _getMultisigTransactionCalldata(); | ||
TimelockController timelock = TimelockController(payable(this._timelock())); | ||
timelock.execute( | ||
this._executorMultisig(), | ||
0 /* value */, | ||
executorMultisigCalldata, | ||
0 /* predecessor */, | ||
bytes32(0) /* salt */ | ||
); | ||
} | ||
|
||
function testDeploy() public override { | ||
// save the previous implementation address to assert its change later | ||
address prevRewardsCoordinator = zDeployedImpl(type(RewardsCoordinator).name); | ||
|
||
// 0. Deploy the Implementation contract. | ||
runAsEOA(); | ||
|
||
// 1. run the queue script. | ||
vm.startPrank(this._operationsMultisig()); | ||
super.runAsMultisig(); | ||
vm.stopPrank(); | ||
|
||
RewardsCoordinator rewardsCoordinatorProxy = RewardsCoordinator(zDeployedProxy(type(RewardsCoordinator).name)); | ||
uint256 pausedStatusBefore = rewardsCoordinatorProxy.paused(); | ||
TimelockController timelock = this._timelock(); | ||
|
||
// 2. run the execute script above. | ||
bytes memory multisigTxnData = _getMultisigTransactionCalldata(); | ||
bytes32 txHash = timelock.hashOperation(this._executorMultisig(), 0, multisigTxnData, 0, 0); | ||
|
||
assertEq(timelock.isOperationPending(txHash), true, "Transaction should be queued and pending."); | ||
vm.warp(block.timestamp + timelock.getMinDelay()); // 1 tick after ETA. | ||
|
||
assertEq(timelock.isOperationReady(txHash), true, "Transaction should be executable."); | ||
|
||
vm.expectEmit(true, true, true, true, address(rewardsCoordinatorProxy)); | ||
emit Upgraded(zDeployedImpl(type(RewardsCoordinator).name)); | ||
execute(); | ||
|
||
// 3. assert that the execute did something | ||
assertEq(timelock.isOperationDone(txHash), true, "Transaction should be executed."); | ||
|
||
// assert that the proxy implementation was updated. | ||
ProxyAdmin admin = ProxyAdmin(this._proxyAdmin()); | ||
address rewardsCoordinatorImpl = admin.getProxyImplementation( | ||
TransparentUpgradeableProxy(payable(zDeployedProxy(type(RewardsCoordinator).name))) | ||
); | ||
assertEq(rewardsCoordinatorImpl, zDeployedImpl(type(RewardsCoordinator).name)); | ||
assertNotEq(prevRewardsCoordinator, rewardsCoordinatorImpl, "expected rewardsCoordinatorImpl to be different"); | ||
|
||
uint256 pausedStatusAfter = rewardsCoordinatorProxy.paused(); | ||
address owner = this._operationsMultisig(); | ||
IPauserRegistry pauserRegistry = IPauserRegistry(this._pauserRegistry()); | ||
uint64 initPausedStatus = zUint64("REWARDS_COORDINATOR_INIT_PAUSED_STATUS"); | ||
address rewardsUpdater = zAddress("REWARDS_COORDINATOR_UPDATER"); | ||
uint32 activationDelay = zUint32("REWARDS_COORDINATOR_ACTIVATION_DELAY"); | ||
uint16 defaultOperatorSplitBips = zUint16("REWARDS_COORDINATOR_DEFAULT_OPERATOR_SPLIT_BIPS"); | ||
|
||
// Ensure that the proxy contract cannot be re-initialized. | ||
vm.expectRevert("Initializable: contract is already initialized"); | ||
rewardsCoordinatorProxy.initialize( | ||
owner, | ||
pauserRegistry, | ||
initPausedStatus, | ||
rewardsUpdater, | ||
activationDelay, | ||
defaultOperatorSplitBips | ||
); | ||
|
||
// Assert Immutables and State Variables set through initialize | ||
assertEq(rewardsCoordinatorProxy.owner(), owner, "expected owner"); | ||
assertEq(address(rewardsCoordinatorProxy.pauserRegistry()), address(pauserRegistry), "expected pauserRegistry"); | ||
assertEq(address(rewardsCoordinatorProxy.rewardsUpdater()), rewardsUpdater, "expected rewardsUpdater"); | ||
assertEq(rewardsCoordinatorProxy.activationDelay(), activationDelay, "expected activationDelay"); | ||
assertEq( | ||
rewardsCoordinatorProxy.defaultOperatorSplitBips(), | ||
defaultOperatorSplitBips, | ||
"expected defaultOperatorSplitBips" | ||
); | ||
assertEq( | ||
pausedStatusBefore, | ||
pausedStatusAfter, | ||
"expected paused status to be the same before and after initialization" | ||
); | ||
assertEq( | ||
address(rewardsCoordinatorProxy.delegationManager()), | ||
zDeployedProxy(type(DelegationManager).name), | ||
"expected delegationManager" | ||
); | ||
assertEq( | ||
address(rewardsCoordinatorProxy.strategyManager()), | ||
zDeployedProxy(type(StrategyManager).name), | ||
"expected strategyManager" | ||
); | ||
|
||
assertEq( | ||
rewardsCoordinatorProxy.CALCULATION_INTERVAL_SECONDS(), | ||
zUint32("REWARDS_COORDINATOR_CALCULATION_INTERVAL_SECONDS"), | ||
"expected REWARDS_COORDINATOR_CALCULATION_INTERVAL_SECONDS" | ||
); | ||
assertEq( | ||
rewardsCoordinatorProxy.CALCULATION_INTERVAL_SECONDS(), | ||
1 days, | ||
"expected REWARDS_COORDINATOR_CALCULATION_INTERVAL_SECONDS" | ||
); | ||
assertGt( | ||
rewardsCoordinatorProxy.CALCULATION_INTERVAL_SECONDS(), | ||
0, | ||
"expected non-zero REWARDS_COORDINATOR_CALCULATION_INTERVAL_SECONDS" | ||
); | ||
|
||
assertEq(rewardsCoordinatorProxy.MAX_REWARDS_DURATION(), zUint32("REWARDS_COORDINATOR_MAX_REWARDS_DURATION")); | ||
assertGt(rewardsCoordinatorProxy.MAX_REWARDS_DURATION(), 0); | ||
|
||
assertEq( | ||
rewardsCoordinatorProxy.MAX_RETROACTIVE_LENGTH(), | ||
zUint32("REWARDS_COORDINATOR_MAX_RETROACTIVE_LENGTH") | ||
); | ||
assertGt(rewardsCoordinatorProxy.MAX_RETROACTIVE_LENGTH(), 0); | ||
|
||
assertEq(rewardsCoordinatorProxy.MAX_FUTURE_LENGTH(), zUint32("REWARDS_COORDINATOR_MAX_FUTURE_LENGTH")); | ||
assertGt(rewardsCoordinatorProxy.MAX_FUTURE_LENGTH(), 0); | ||
|
||
assertEq( | ||
rewardsCoordinatorProxy.GENESIS_REWARDS_TIMESTAMP(), | ||
zUint32("REWARDS_COORDINATOR_GENESIS_REWARDS_TIMESTAMP") | ||
); | ||
assertGt(rewardsCoordinatorProxy.GENESIS_REWARDS_TIMESTAMP(), 0); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"name": "rewards-v2-patch", | ||
"from": "~0.0.0", | ||
"to": "0.5.2", | ||
"phases": [ | ||
{ | ||
"type": "eoa", | ||
"filename": "1-eoa.s.sol" | ||
}, | ||
{ | ||
"type": "multisig", | ||
"filename": "2-multisig.s.sol" | ||
}, | ||
{ | ||
"type": "multisig", | ||
"filename": "3-multisig.s.sol" | ||
} | ||
] | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
identical to 0.5.1 but sets
REWARDS_COORDINATOR_CALCULATION_INTERVAL_SECONDS
= 1 day