Skip to content
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 3 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions script/releases/v0.5.2-rewardsv2/1-eoa.s.sol
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 {
Copy link
Contributor

@jbrower95 jbrower95 Dec 10, 2024

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

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.");
}
}
82 changes: 82 additions & 0 deletions script/releases/v0.5.2-rewardsv2/2-multisig.s.sol
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.");
}
}
160 changes: 160 additions & 0 deletions script/releases/v0.5.2-rewardsv2/3-multisig.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// 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 override view 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"
);
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);
}
}
19 changes: 19 additions & 0 deletions script/releases/v0.5.2-rewardsv2/upgrade.json
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"
}
]
}
Loading