Skip to content

Commit

Permalink
Add setClaimerFor function call
Browse files Browse the repository at this point in the history
  • Loading branch information
bxmmm1 committed Jun 20, 2024
1 parent a466a70 commit 3ecdd0b
Show file tree
Hide file tree
Showing 17 changed files with 192 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0 <0.9.0;

import { Script } from "forge-std/Script.sol";
import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol";
import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol";
import { console } from "forge-std/console.sol";
import { ROLE_ID_DAO } from "../../script/Roles.sol";
import { PufferModuleManager } from "../../src/PufferModuleManager.sol";

/**
* @title GenerateAccessManagerCalldata2
* @author Puffer Finance
* @notice Generates the AccessManager call data to setup the public access
* The returned calldata is queued and executed by the Operations Multisig
* 1. timelock.queueTransaction(address(accessManager), encodedMulticall, 1)
* 2. ... 7 days later ...
* 3. timelock.executeTransaction(address(accessManager), encodedMulticall, 1)
*/
contract GenerateAccessManagerCalldata2 is Script {
function run(address moduleManager) public pure returns (bytes memory) {
bytes[] memory calldatas = new bytes[](1);

bytes4[] memory daoSelectors = new bytes4[](1);
daoSelectors[0] = PufferModuleManager.callSetClaimerFor.selector;

calldatas[0] = abi.encodeWithSelector(
AccessManager.setTargetFunctionRole.selector, moduleManager, daoSelectors, ROLE_ID_DAO
);

bytes memory encodedMulticall = abi.encodeCall(Multicall.multicall, (calldatas));

// console.log("GenerateAccessManagerCallData:");
// console.logBytes(encodedMulticall);

return encodedMulticall;
}
}
7 changes: 5 additions & 2 deletions mainnet-contracts/script/DeployProtocolToMainnet.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { SetupAccess } from "script/SetupAccess.s.sol";
import { OperationsCoordinator } from "../src/OperationsCoordinator.sol";
import { AVSContractsRegistry } from "../src/AVSContractsRegistry.sol";
import { ValidatorTicketPricer } from "../src/ValidatorTicketPricer.sol";
import { IRewardsCoordinator } from "../src/interface/EigenLayer/IRewardsCoordinator.sol";

/**
* // Check that the simulation
Expand Down Expand Up @@ -147,13 +148,15 @@ contract DeployProtocolToMainnet is Script {
eigenPodManager: EIGEN_POD_MANAGER,
eigenWithdrawalRouter: IDelayedWithdrawalRouter(DELAYED_WITHDRAWAL_ROUTER),
delegationManager: IDelegationManager(DELEGATION_MANAGER),
moduleManager: PufferModuleManager(address(moduleManagerProxy))
moduleManager: PufferModuleManager(address(moduleManagerProxy)),
rewardsCoordinator: IRewardsCoordinator(address(0))
});

restakingOperatorImplementation = new RestakingOperator({
delegationManager: IDelegationManager(DELEGATION_MANAGER),
slasher: ISlasher(EIGEN_SLASHER),
moduleManager: PufferModuleManager(address(moduleManagerProxy))
moduleManager: PufferModuleManager(address(moduleManagerProxy)),
rewardsCoordinator: IRewardsCoordinator(address(0))
});

pufferModuleBeacon = new UpgradeableBeacon(address(moduleImplementation), address(accessManager));
Expand Down
13 changes: 10 additions & 3 deletions mainnet-contracts/script/DeployPuffer.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ import { ValidatorTicketPricer } from "../src/ValidatorTicketPricer.sol";
import { OperationsCoordinator } from "../src/OperationsCoordinator.sol";
import { PufferOracleV2 } from "../src/PufferOracleV2.sol";
import { IPufferOracleV2 } from "../src/interface/IPufferOracleV2.sol";
import { IRewardsCoordinator } from "../src/interface/EigenLayer/IRewardsCoordinator.sol";
import { AVSContractsRegistry } from "../src/AVSContractsRegistry.sol";
import { RewardsCoordinatorMock } from "../test/mocks/RewardsCoordinatorMock.sol";

/**
* @title DeployPuffer
Expand Down Expand Up @@ -59,6 +61,7 @@ contract DeployPuffer is BaseScript {
address eigenPodManager;
address delayedWithdrawalRouter;
address delegationManager;
address rewardsCoordinator;
address eigenSlasher;
address treasury;

Expand All @@ -75,13 +78,15 @@ contract DeployPuffer is BaseScript {
delayedWithdrawalRouter = 0x7Fe7E9CC0F274d2435AD5d56D5fa73E47F6A23D8;
delegationManager = 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A;
eigenSlasher = 0xD92145c07f8Ed1D392c1B88017934E301CC1c3Cd;
rewardsCoordinator = address(0); //@todo
treasury = vm.envAddress("TREASURY");
} else if (isAnvil()) {
// Local chain / tests
eigenPodManager = address(new EigenPodManagerMock());
delayedWithdrawalRouter = address(0);
delegationManager = address(new DelegationManagerMock());
eigenSlasher = vm.envOr("EIGEN_SLASHER", address(1)); //@todo
rewardsCoordinator = address(new RewardsCoordinatorMock());
eigenSlasher = vm.envOr("EIGEN_SLASHER", address(1)); // @todo
treasury = address(1);
} else {
// Holesky
Expand Down Expand Up @@ -123,14 +128,16 @@ contract DeployPuffer is BaseScript {
eigenPodManager: eigenPodManager,
eigenWithdrawalRouter: IDelayedWithdrawalRouter(delayedWithdrawalRouter),
delegationManager: IDelegationManager(delegationManager),
moduleManager: PufferModuleManager(address(moduleManagerProxy))
moduleManager: PufferModuleManager(address(moduleManagerProxy)),
rewardsCoordinator: IRewardsCoordinator(rewardsCoordinator)
});
vm.label(address(moduleImplementation), "PufferModuleImplementation");

RestakingOperator restakingOperatorImplementation = new RestakingOperator(
IDelegationManager(delegationManager),
ISlasher(eigenSlasher),
PufferModuleManager(address(moduleManagerProxy))
PufferModuleManager(address(moduleManagerProxy)),
IRewardsCoordinator(rewardsCoordinator)
);

pufferModuleBeacon = new UpgradeableBeacon(address(moduleImplementation), address(accessManager));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { PufferModule } from "../src/PufferModule.sol";
import { IDelayedWithdrawalRouter } from "eigenlayer/interfaces/IDelayedWithdrawalRouter.sol";
import { IDelegationManager } from "eigenlayer/interfaces/IDelegationManager.sol";
import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
import { IRewardsCoordinator } from "../src/interface/EigenLayer/IRewardsCoordinator.sol";

/**
* forge script script/DeployPufferModuleImplementation.s.sol:DeployPufferModuleImplementation --rpc-url=$RPC_URL --private-key $PK
Expand All @@ -33,7 +34,8 @@ contract DeployPufferModuleImplementation is Script {
eigenPodManager: 0x30770d7E3e71112d7A6b7259542D1f680a70e315,
eigenWithdrawalRouter: IDelayedWithdrawalRouter(0x642c646053eaf2254f088e9019ACD73d9AE0FA32),
delegationManager: IDelegationManager(0xA44151489861Fe9e3055d95adC98FbD462B948e7),
moduleManager: PufferModuleManager(0xe4695ab93163F91665Ce5b96527408336f070a71)
moduleManager: PufferModuleManager(0xe4695ab93163F91665Ce5b96527408336f070a71),
rewardsCoordinator: IRewardsCoordinator(address(0))
});

bytes memory cd = abi.encodeCall(UpgradeableBeacon.upgradeTo, address(newImpl));
Expand Down
4 changes: 3 additions & 1 deletion mainnet-contracts/script/DeployRestakingOperator.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { RestakingOperator } from "../src/RestakingOperator.sol";
import { IDelegationManager } from "eigenlayer/interfaces/IDelegationManager.sol";
import { ISlasher } from "eigenlayer/interfaces/ISlasher.sol";
import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
import { IRewardsCoordinator } from "../src/interface/EigenLayer/IRewardsCoordinator.sol";

/**
* forge script script/DeployRestakingOperator.s.sol:DeployRestakingOperator --rpc-url=$RPC_URL --private-key $PK
Expand All @@ -25,7 +26,8 @@ contract DeployRestakingOperator is Script {
RestakingOperator impl = new RestakingOperator({
delegationManager: IDelegationManager(0xA44151489861Fe9e3055d95adC98FbD462B948e7),
slasher: ISlasher(0xcAe751b75833ef09627549868A04E32679386e7C),
moduleManager: IPufferModuleManager(0xe4695ab93163F91665Ce5b96527408336f070a71)
moduleManager: IPufferModuleManager(0xe4695ab93163F91665Ce5b96527408336f070a71),
rewardsCoordinator: IRewardsCoordinator(address(0))
});

bytes memory cd = abi.encodeCall(UpgradeableBeacon.upgradeTo, address(impl));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { RestakingOperator } from "../../src/RestakingOperator.sol";
import { IDelegationManager } from "eigenlayer/interfaces/IDelegationManager.sol";
import { ISlasher } from "eigenlayer/interfaces/ISlasher.sol";
import { GenerateAccessManagerCalldata1 } from "script/AccessManagerMigrations/GenerateAccessManagerCalldata1.s.sol";
import { IRewardsCoordinator } from "../../src/interface/EigenLayer/IRewardsCoordinator.sol";

/**
* forge script script/MainnetContractMigrations/UpgradeRestakingOperator.s.sol:UpgradeRestakingOperator --rpc-url=$RPC_URL --private-key $PK
Expand Down Expand Up @@ -45,7 +46,8 @@ contract UpgradeRestakingOperator is Script {
RestakingOperator restakingOperatorImpl = new RestakingOperator({
delegationManager: IDelegationManager(DELEGATION_MANAGER),
slasher: ISlasher(EIGEN_SLASHER),
moduleManager: PufferModuleManager(MODULE_MANAGER_PROXY)
moduleManager: PufferModuleManager(MODULE_MANAGER_PROXY),
rewardsCoordinator: IRewardsCoordinator(address(0))
});

bytes memory accessCd =
Expand Down
9 changes: 9 additions & 0 deletions mainnet-contracts/script/SetupAccess.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import { PufferVaultV2 } from "../src/PufferVaultV2.sol";
import { OperationsCoordinator } from "../src/OperationsCoordinator.sol";
import { ValidatorTicketPricer } from "../src/ValidatorTicketPricer.sol";
import { GenerateAccessManagerCallData } from "../script/GenerateAccessManagerCallData.sol";
import { GenerateAccessManagerCalldata2 } from "../script/AccessManagerMigrations/GenerateAccessManagerCalldata2.s.sol";

import {
ROLE_ID_OPERATIONS_MULTISIG,
ROLE_ID_OPERATIONS_PAYMASTER,
Expand Down Expand Up @@ -55,15 +57,22 @@ contract SetupAccess is BaseScript {
require(s, "failed setupAccess GenerateAccessManagerCallData 1");

// This will be executed by the operations multisig on mainnet
// PufferVaultV2 access setup
bytes memory cd = new GenerateAccessManagerCallData().run(deployment.pufferVault, deployment.pufferDepositor);
// console.logBytes(cd);
(s,) = address(accessManager).call(cd);
require(s, "failed setupAccess GenerateAccessManagerCallData");

// AvsContractsRegistry setup
cd = new GenerateAccessManagerCalldata1().run(deployment.moduleManager, deployment.aVSContractsRegistry, DAO);
// console.logBytes(cd);
(s,) = address(accessManager).call(cd);
require(s, "failed setupAccess GenerateAccessManagerCalldata1");

// PufferModuleManager.setTargetFunctionRole.selector setup
cd = new GenerateAccessManagerCalldata2().run(deployment.moduleManager);
(s,) = address(accessManager).call(cd);
require(s, "failed setupAccess GenerateAccessManagerCalldata2");
}

function _generateAccessCalldata(
Expand Down
18 changes: 17 additions & 1 deletion mainnet-contracts/src/PufferModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { LibGuardianMessages } from "./LibGuardianMessages.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { ModuleStorage } from "./struct/ModuleStorage.sol";
import { IRewardsCoordinator } from "./interface/EigenLayer/IRewardsCoordinator.sol";

/**
* @title PufferModule
Expand All @@ -42,6 +43,11 @@ contract PufferModule is IPufferModule, Initializable, AccessManagedUpgradeable
*/
IEigenPodManager public immutable EIGEN_POD_MANAGER;

/**
* @dev Upgradeable contract from EigenLayer
*/
IRewardsCoordinator public immutable EIGEN_REWARDS_COORDINATOR;

/**
* @dev Upgradeable contract from EigenLayer
*/
Expand Down Expand Up @@ -71,13 +77,15 @@ contract PufferModule is IPufferModule, Initializable, AccessManagedUpgradeable
address eigenPodManager,
IDelayedWithdrawalRouter eigenWithdrawalRouter,
IDelegationManager delegationManager,
IPufferModuleManager moduleManager
IPufferModuleManager moduleManager,
IRewardsCoordinator rewardsCoordinator
) payable {
EIGEN_POD_MANAGER = IEigenPodManager(eigenPodManager);
EIGEN_WITHDRAWAL_ROUTER = eigenWithdrawalRouter;
EIGEN_DELEGATION_MANAGER = delegationManager;
PUFFER_PROTOCOL = protocol;
PUFFER_MODULE_MANAGER = moduleManager;
EIGEN_REWARDS_COORDINATOR = rewardsCoordinator;
_disableInitializers();
}

Expand Down Expand Up @@ -329,6 +337,14 @@ contract PufferModule is IPufferModule, Initializable, AccessManagedUpgradeable
return EIGEN_DELEGATION_MANAGER.undelegate(address(this));
}

/**
* @inheritdoc IPufferModule
* @dev Restricted to PufferModuleManager
*/
function callSetClaimerFor(address claimer) external virtual onlyPufferModuleManager {
EIGEN_REWARDS_COORDINATOR.setClaimerFor(claimer);
}

/**
* @notice Returns the block number of when the latest rewards proof was posted
*/
Expand Down
10 changes: 10 additions & 0 deletions mainnet-contracts/src/PufferModuleManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,16 @@ contract PufferModuleManager is IPufferModuleManager, AccessManagedUpgradeable,
emit WithdrawalsQueued(moduleName, sharesAmount, withdrawalRoots[0]);
}

/**
* @inheritdoc IPufferModuleManager
* @dev Restricted to the DAO
*/
function callSetClaimerFor(address moduleOrReOp, address claimer) external virtual restricted {
// We can cast `moduleOrReOp` to IPufferModule/IRestakingOperator, uses the same function signature.
IPufferModule(moduleOrReOp).callSetClaimerFor(claimer);
emit ClaimerSet({ rewardsReceiver: moduleOrReOp, claimer: claimer });
}

/**
* @inheritdoc IPufferModuleManager
* @dev Restricted to the DAO
Expand Down
22 changes: 21 additions & 1 deletion mainnet-contracts/src/RestakingOperator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { IRegistryCoordinator, IBLSApkRegistry } from "eigenlayer-middleware/interfaces/IRegistryCoordinator.sol";
import { IRegistryCoordinatorExtended } from "./interface/IRegistryCoordinatorExtended.sol";
import { ISignatureUtils } from "eigenlayer/interfaces/ISignatureUtils.sol";
import { IRewardsCoordinator } from "./interface/EigenLayer/IRewardsCoordinator.sol";

/**
* @title RestakingOperator
Expand All @@ -27,6 +28,11 @@ contract RestakingOperator is IRestakingOperator, IERC1271, Initializable, Acces
// keccak256(abi.encode(uint256(keccak256("RestakingOperator.storage")) - 1)) & ~bytes32(uint256(0xff))
// slither-disable-next-line unused-state

/**
* @dev Upgradeable contract from EigenLayer
*/
IRewardsCoordinator public immutable EIGEN_REWARDS_COORDINATOR;

bytes32 private constant _RESTAKING_OPERATOR_STORAGE =
0x2182a68f8e463a6b4c76f5de5bb25b7b51ccc88cb3b9ba6c251c356b50555100;

Expand Down Expand Up @@ -70,7 +76,12 @@ contract RestakingOperator is IRestakingOperator, IERC1271, Initializable, Acces
}

// We use constructor to set the immutable variables
constructor(IDelegationManager delegationManager, ISlasher slasher, IPufferModuleManager moduleManager) {
constructor(
IDelegationManager delegationManager,
ISlasher slasher,
IPufferModuleManager moduleManager,
IRewardsCoordinator rewardsCoordinator
) {
if (address(delegationManager) == address(0)) {
revert InvalidAddress();
}
Expand All @@ -83,6 +94,7 @@ contract RestakingOperator is IRestakingOperator, IERC1271, Initializable, Acces
EIGEN_DELEGATION_MANAGER = delegationManager;
EIGEN_SLASHER = slasher;
PUFFER_MODULE_MANAGER = moduleManager;
EIGEN_REWARDS_COORDINATOR = rewardsCoordinator;
_disableInitializers();
}

Expand Down Expand Up @@ -212,6 +224,14 @@ contract RestakingOperator is IRestakingOperator, IERC1271, Initializable, Acces
IRegistryCoordinatorExtended(avsRegistryCoordinator).updateSocket(socket);
}

/**
* @inheritdoc IRestakingOperator
* @dev Restricted to PufferModuleManager
*/
function callSetClaimerFor(address claimer) external virtual onlyPufferModuleManager {
EIGEN_REWARDS_COORDINATOR.setClaimerFor(claimer);
}

/**
* @notice Verifies that the signer is the owner of the signing contract.
*/
Expand Down
20 changes: 20 additions & 0 deletions mainnet-contracts/src/interface/EigenLayer/IRewardsCoordinator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;

/**
* @title RewardsCoordinator
* @author Eigen Labs Inc.
* @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service
* @notice This is the contract for rewards in EigenLayer. The main functionalities of this contract are
* - enabling any ERC20 rewards from AVSs to their operators and stakers for a given time range
* - allowing stakers and operators to claim their earnings including a commission bips for operators
* - allowing the protocol to provide ERC20 tokens to stakers over a specified time range
*/
interface IRewardsCoordinator {
/**
* @notice Sets the address of the entity that can call `processClaim` on behalf of the earner (msg.sender)
* @param claimer The address of the entity that can call `processClaim` on behalf of the earner
* @dev Only callable by the `earner`
*/
function setClaimerFor(address claimer) external;
}
5 changes: 5 additions & 0 deletions mainnet-contracts/src/interface/IPufferModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,9 @@ interface IPufferModule {
function call(address to, uint256 amount, bytes calldata data)
external
returns (bool success, bytes memory response);

/**
* @notice Sets the rewards claimer to `claimer` for the PufferModule
*/
function callSetClaimerFor(address claimer) external;
}
14 changes: 14 additions & 0 deletions mainnet-contracts/src/interface/IPufferModuleManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,12 @@ interface IPufferModuleManager {
IRestakingOperator restakingOperator, address avsRegistryCoordinator, string socket
);

/**
* @notice Emitted when the Restaking Operator or PufferModule sets the calimer to `claimer`
* @dev Signature "0x4925eafc82d0c4d67889898eeed64b18488ab19811e61620f387026dec126a28"
*/
event ClaimerSet(address indexed rewardsReceiver, address indexed claimer);

/**
* @notice Returns the Puffer Module beacon address
*/
Expand Down Expand Up @@ -408,6 +414,14 @@ interface IPufferModuleManager {
string memory socket
) external;

/**
* @notice Calls the `callSetClaimerFor` function on the target module or restaking operator contract
* @param moduleOrReOp is the address of the target module or restaking operator contract
* @param claimer is the address of the claimer to be set
* @dev Restricted to the DAO
*/
function callSetClaimerFor(address moduleOrReOp, address claimer) external;

/**
* @notice Calls the `target` contract with `customCalldata` from the Restaking Operator contract
* @param restakingOperator is the Restaking Operator contract
Expand Down
5 changes: 5 additions & 0 deletions mainnet-contracts/src/interface/IRestakingOperator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,9 @@ interface IRestakingOperator {
* @param socket is the new socket of the operator
*/
function updateOperatorAVSSocket(address avsRegistryCoordinator, string memory socket) external;

/**
* @notice Sets the rewards claimer to `claimer` for the RestakingOperator
*/
function callSetClaimerFor(address claimer) external;
}
Loading

0 comments on commit 3ecdd0b

Please sign in to comment.