diff --git a/chainio/clients/builder.go b/chainio/clients/builder.go index 0526e6f1..17b31281 100644 --- a/chainio/clients/builder.go +++ b/chainio/clients/builder.go @@ -198,6 +198,7 @@ func (config *BuildAllConfig) BuildELClients( elContractBindings.DelegationManager, elContractBindings.StrategyManager, elContractBindings.AvsDirectory, + elContractBindings.RewardsCoordinator, logger, ethHttpClient, ) diff --git a/chainio/clients/elcontracts/reader.go b/chainio/clients/elcontracts/reader.go index abf7c707..b11206b2 100644 --- a/chainio/clients/elcontracts/reader.go +++ b/chainio/clients/elcontracts/reader.go @@ -2,6 +2,7 @@ package elcontracts import ( "errors" + "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -12,6 +13,7 @@ import ( avsdirectory "github.com/Layr-Labs/eigensdk-go/contracts/bindings/AVSDirectory" delegationmanager "github.com/Layr-Labs/eigensdk-go/contracts/bindings/DelegationManager" erc20 "github.com/Layr-Labs/eigensdk-go/contracts/bindings/IERC20" + rewardscoordinator "github.com/Layr-Labs/eigensdk-go/contracts/bindings/IRewardsCoordinator" slasher "github.com/Layr-Labs/eigensdk-go/contracts/bindings/ISlasher" strategy "github.com/Layr-Labs/eigensdk-go/contracts/bindings/IStrategy" strategymanager "github.com/Layr-Labs/eigensdk-go/contracts/bindings/StrategyManager" @@ -58,6 +60,8 @@ type ELReader interface { CalculateOperatorAVSRegistrationDigestHash( opts *bind.CallOpts, operator gethcommon.Address, avs gethcommon.Address, salt [32]byte, expiry *big.Int, ) ([32]byte, error) + + GetDistributionRootsLength(opts *bind.CallOpts) (*big.Int, error) } type Config struct { @@ -67,12 +71,13 @@ type Config struct { } type ELChainReader struct { - logger logging.Logger - slasher slasher.ContractISlasherCalls - delegationManager *delegationmanager.ContractDelegationManager - strategyManager *strategymanager.ContractStrategyManager - avsDirectory *avsdirectory.ContractAVSDirectory - ethClient eth.Client + logger logging.Logger + slasher slasher.ContractISlasherCalls + delegationManager *delegationmanager.ContractDelegationManager + strategyManager *strategymanager.ContractStrategyManager + avsDirectory *avsdirectory.ContractAVSDirectory + rewardsCoordinator *rewardscoordinator.ContractIRewardsCoordinator + ethClient eth.Client } // forces EthReader to implement the chainio.Reader interface @@ -83,18 +88,20 @@ func NewELChainReader( delegationManager *delegationmanager.ContractDelegationManager, strategyManager *strategymanager.ContractStrategyManager, avsDirectory *avsdirectory.ContractAVSDirectory, + rewardsCoordinator *rewardscoordinator.ContractIRewardsCoordinator, logger logging.Logger, ethClient eth.Client, ) *ELChainReader { logger = logger.With(logging.ComponentKey, "elcontracts/reader") return &ELChainReader{ - slasher: slasher, - delegationManager: delegationManager, - strategyManager: strategyManager, - avsDirectory: avsDirectory, - logger: logger, - ethClient: ethClient, + slasher: slasher, + delegationManager: delegationManager, + strategyManager: strategyManager, + avsDirectory: avsDirectory, + rewardsCoordinator: rewardsCoordinator, + logger: logger, + ethClient: ethClient, } } @@ -120,6 +127,7 @@ func BuildELChainReader( elContractBindings.DelegationManager, elContractBindings.StrategyManager, elContractBindings.AvsDirectory, + elContractBindings.RewardsCoordinator, logger, ethClient, ), nil @@ -143,6 +151,7 @@ func NewReaderFromConfig( elContractBindings.DelegationManager, elContractBindings.StrategyManager, elContractBindings.AvsDirectory, + elContractBindings.RewardsCoordinator, logger, ethClient, ), nil @@ -294,3 +303,11 @@ func (r *ELChainReader) CalculateOperatorAVSRegistrationDigestHash( opts, operator, avs, salt, expiry, ) } + +func (r *ELChainReader) GetDistributionRootsLength(opts *bind.CallOpts) (*big.Int, error) { + if r.rewardsCoordinator == nil { + return nil, errors.New("RewardsCoordinator contract not provided") + } + + return r.rewardsCoordinator.GetDistributionRootsLength(opts) +} diff --git a/chainio/clients/elcontracts/writer.go b/chainio/clients/elcontracts/writer.go index 0699280d..71286ddc 100644 --- a/chainio/clients/elcontracts/writer.go +++ b/chainio/clients/elcontracts/writer.go @@ -45,6 +45,12 @@ type ELWriter interface { ctx context.Context, claimer gethcommon.Address, ) (*gethtypes.Receipt, error) + + ProcessClaim( + ctx context.Context, + claim rewardscoordinator.IRewardsCoordinatorRewardsMerkleClaim, + earnerAddress gethcommon.Address, + ) (*gethtypes.Receipt, error) } type ELChainWriter struct { @@ -112,6 +118,7 @@ func BuildELChainWriter( elContractBindings.DelegationManager, elContractBindings.StrategyManager, elContractBindings.AvsDirectory, + elContractBindings.RewardsCoordinator, logger, ethClient, ) @@ -119,7 +126,7 @@ func BuildELChainWriter( elContractBindings.Slasher, elContractBindings.DelegationManager, elContractBindings.StrategyManager, - nil, + elContractBindings.RewardsCoordinator, elContractBindings.StrategyManagerAddr, elChainReader, ethClient, @@ -149,6 +156,7 @@ func NewWriterFromConfig( elContractBindings.DelegationManager, elContractBindings.StrategyManager, elContractBindings.AvsDirectory, + elContractBindings.RewardsCoordinator, logger, ethClient, ) @@ -329,3 +337,29 @@ func (w *ELChainWriter) SetClaimerFor( return receipt, nil } + +func (w *ELChainWriter) ProcessClaim( + ctx context.Context, + claim rewardscoordinator.IRewardsCoordinatorRewardsMerkleClaim, + earnerAddress gethcommon.Address, +) (*gethtypes.Receipt, error) { + if w.rewardsCoordinator == nil { + return nil, errors.New("RewardsCoordinator contract not provided") + } + + noSendTxOpts, err := w.txMgr.GetNoSendTxOpts() + if err != nil { + return nil, utils.WrapError("failed to get no send tx opts", err) + } + + tx, err := w.rewardsCoordinator.ProcessClaim(noSendTxOpts, claim, earnerAddress) + if err != nil { + return nil, utils.WrapError("failed to create ProcessClaim tx", err) + } + receipt, err := w.txMgr.Send(ctx, tx) + if err != nil { + return nil, utils.WrapError("failed to send tx", err) + } + + return receipt, nil +} diff --git a/chainio/mocks/elContractsReader.go b/chainio/mocks/elContractsReader.go index 1ba7173e..03881c98 100644 --- a/chainio/mocks/elContractsReader.go +++ b/chainio/mocks/elContractsReader.go @@ -74,6 +74,21 @@ func (mr *MockELReaderMockRecorder) CalculateOperatorAVSRegistrationDigestHash(a return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CalculateOperatorAVSRegistrationDigestHash", reflect.TypeOf((*MockELReader)(nil).CalculateOperatorAVSRegistrationDigestHash), arg0, arg1, arg2, arg3, arg4) } +// GetDistributionRootsLength mocks base method. +func (m *MockELReader) GetDistributionRootsLength(arg0 *bind.CallOpts) (*big.Int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDistributionRootsLength", arg0) + ret0, _ := ret[0].(*big.Int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetDistributionRootsLength indicates an expected call of GetDistributionRootsLength. +func (mr *MockELReaderMockRecorder) GetDistributionRootsLength(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDistributionRootsLength", reflect.TypeOf((*MockELReader)(nil).GetDistributionRootsLength), arg0) +} + // GetOperatorDetails mocks base method. func (m *MockELReader) GetOperatorDetails(arg0 *bind.CallOpts, arg1 types.Operator) (types.Operator, error) { m.ctrl.T.Helper() diff --git a/chainio/mocks/elContractsWriter.go b/chainio/mocks/elContractsWriter.go index f497184f..b4c1c982 100644 --- a/chainio/mocks/elContractsWriter.go +++ b/chainio/mocks/elContractsWriter.go @@ -14,6 +14,7 @@ import ( big "math/big" reflect "reflect" + contractIRewardsCoordinator "github.com/Layr-Labs/eigensdk-go/contracts/bindings/IRewardsCoordinator" types "github.com/Layr-Labs/eigensdk-go/types" common "github.com/ethereum/go-ethereum/common" types0 "github.com/ethereum/go-ethereum/core/types" @@ -58,6 +59,21 @@ func (mr *MockELWriterMockRecorder) DepositERC20IntoStrategy(arg0, arg1, arg2 an return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DepositERC20IntoStrategy", reflect.TypeOf((*MockELWriter)(nil).DepositERC20IntoStrategy), arg0, arg1, arg2) } +// ProcessClaim mocks base method. +func (m *MockELWriter) ProcessClaim(arg0 context.Context, arg1 contractIRewardsCoordinator.IRewardsCoordinatorRewardsMerkleClaim, arg2 common.Address) (*types0.Receipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ProcessClaim", arg0, arg1, arg2) + ret0, _ := ret[0].(*types0.Receipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ProcessClaim indicates an expected call of ProcessClaim. +func (mr *MockELWriterMockRecorder) ProcessClaim(arg0, arg1, arg2 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessClaim", reflect.TypeOf((*MockELWriter)(nil).ProcessClaim), arg0, arg1, arg2) +} + // RegisterAsOperator mocks base method. func (m *MockELWriter) RegisterAsOperator(arg0 context.Context, arg1 types.Operator) (*types0.Receipt, error) { m.ctrl.T.Helper()