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