Skip to content

Commit 2c27ace

Browse files
committed
feat: rewards example
1 parent b42aa0b commit 2c27ace

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.12;
3+
4+
import "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol";
5+
import "../src/StakeRegistry.sol";
6+
import "../src/ServiceManagerBase.sol";
7+
import "forge-std/Script.sol";
8+
import "forge-std/Test.sol";
9+
import "forge-std/StdUtils.sol";
10+
11+
contract RewardSubmissionExample is Script, Test {
12+
13+
// FILL IN THESE VALUES
14+
uint256 AMOUNT_TO_ETH_QUORUM = 1 ether;
15+
uint256 AMOUNT_TO_EIGEN_QUORUM = 1 ether;
16+
uint32 START_TIMESTAMP = 1727913600; // Must be on Thursday 00:00:00 GMT+0000 any given week
17+
uint32 DURATION = 2419200; // Must be multiple of 604800
18+
address SERVICE_MANAGER = 0x870679E138bCdf293b7Ff14dD44b70FC97e12fc0;
19+
address STAKE_REGISTRY = 0x006124Ae7976137266feeBFb3F4D2BE4C073139D;
20+
address TOKEN = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
21+
22+
bytes calldata_to_serviceManager;
23+
24+
// forge test --mc RewardSubmissionExample --fork-url $MAINNET_RPC_URL -vvvv
25+
function test() external {
26+
calldata_to_serviceManager = _getCalldataToServiceManager();
27+
address rewardsInitiator = ServiceManagerBase(SERVICE_MANAGER).rewardsInitiator();
28+
29+
deal(address(TOKEN), rewardsInitiator, AMOUNT_TO_ETH_QUORUM + AMOUNT_TO_EIGEN_QUORUM);
30+
31+
vm.startPrank(rewardsInitiator);
32+
IERC20(TOKEN).approve(SERVICE_MANAGER, AMOUNT_TO_ETH_QUORUM + AMOUNT_TO_EIGEN_QUORUM);
33+
(bool success, ) = address(SERVICE_MANAGER).call(calldata_to_serviceManager);
34+
require(success, "rewards submission failed");
35+
vm.stopPrank();
36+
}
37+
38+
// forge script script/RewardSubmissionExample.s.sol:RewardSubmissionExample --rpc-url $MAINNET_RPC_URL --private-key $MAINNET_PRIVATE_KEY -vvvv // --broadcast
39+
function run() external {
40+
calldata_to_serviceManager = _getCalldataToServiceManager();
41+
42+
vm.startBroadcast();
43+
(bool success, ) = address(SERVICE_MANAGER).call(calldata_to_serviceManager);
44+
require(success, "rewards submission failed");
45+
vm.stopBroadcast();
46+
}
47+
48+
function _getCalldataToServiceManager() public returns (bytes memory _calldata_to_serviceManager) {
49+
IRewardsCoordinator.RewardsSubmission[] memory rewardsSubmissions = new IRewardsCoordinator.RewardsSubmission[](2);
50+
51+
// fetch ETH strategy weights
52+
uint256 length = StakeRegistry(STAKE_REGISTRY).strategyParamsLength(0);
53+
IRewardsCoordinator.StrategyAndMultiplier[] memory ETH_strategyAndMultipliers = new IRewardsCoordinator.StrategyAndMultiplier[](length);
54+
for (uint256 i = 0; i < length; i++) {
55+
(IStrategy strategy, uint96 multiplier) = StakeRegistry(STAKE_REGISTRY).strategyParams(0, i);
56+
ETH_strategyAndMultipliers[i] = IRewardsCoordinator.StrategyAndMultiplier({
57+
strategy: strategy,
58+
multiplier: multiplier
59+
});
60+
}
61+
62+
// strategies must be sorted by address
63+
ETH_strategyAndMultipliers = _sort(ETH_strategyAndMultipliers);
64+
65+
// create ETH rewards submission
66+
rewardsSubmissions[0] = IRewardsCoordinator.RewardsSubmission({
67+
strategiesAndMultipliers: ETH_strategyAndMultipliers,
68+
token: IERC20(TOKEN),
69+
amount: AMOUNT_TO_ETH_QUORUM,
70+
startTimestamp: START_TIMESTAMP,
71+
duration: DURATION
72+
});
73+
74+
// set EIGEN strategy
75+
IRewardsCoordinator.StrategyAndMultiplier[] memory EIGEN_strategyAndMultipliers = new IRewardsCoordinator.StrategyAndMultiplier[](1);
76+
EIGEN_strategyAndMultipliers[0] = IRewardsCoordinator.StrategyAndMultiplier({
77+
strategy: IStrategy(0xaCB55C530Acdb2849e6d4f36992Cd8c9D50ED8F7), // EigenStrategy
78+
multiplier: 1 ether
79+
});
80+
81+
// create EIGEN rewards submission
82+
rewardsSubmissions[1] = IRewardsCoordinator.RewardsSubmission({
83+
strategiesAndMultipliers: EIGEN_strategyAndMultipliers,
84+
token: IERC20(TOKEN),
85+
amount: AMOUNT_TO_EIGEN_QUORUM,
86+
startTimestamp: START_TIMESTAMP,
87+
duration: DURATION
88+
});
89+
90+
// encode calldata to call createAVSRewardsSubmission on ServiceManager
91+
_calldata_to_serviceManager = abi.encodeWithSelector(
92+
ServiceManagerBase.createAVSRewardsSubmission.selector,
93+
rewardsSubmissions
94+
);
95+
96+
emit log_named_bytes("calldata_to_serviceManager", _calldata_to_serviceManager);
97+
return _calldata_to_serviceManager;
98+
}
99+
100+
function _sort(IRewardsCoordinator.StrategyAndMultiplier[] memory strategyAndMultipliers) public pure returns (IRewardsCoordinator.StrategyAndMultiplier[] memory) {
101+
uint length = strategyAndMultipliers.length;
102+
for (uint i = 1; i < length; i++) {
103+
uint key = uint(uint160(address(strategyAndMultipliers[i].strategy)));
104+
uint96 multiplier = strategyAndMultipliers[i].multiplier;
105+
int j = int(i) - 1;
106+
while ((int(j) >= 0) && (uint(uint160(address(strategyAndMultipliers[uint(j)].strategy))) > key)) {
107+
strategyAndMultipliers[uint(j) + 1].strategy = strategyAndMultipliers[uint(j)].strategy;
108+
strategyAndMultipliers[uint(j) + 1].multiplier = strategyAndMultipliers[uint(j)].multiplier;
109+
j--;
110+
}
111+
strategyAndMultipliers[uint(j + 1)].strategy = IStrategy(address(uint160(key)));
112+
strategyAndMultipliers[uint(j + 1)].multiplier = multiplier;
113+
}
114+
return strategyAndMultipliers;
115+
}
116+
}

0 commit comments

Comments
 (0)