From 846ab5bbaad46a8d8bb802baebcfe5abc2a1e8d3 Mon Sep 17 00:00:00 2001 From: Madhur Shrimal Date: Fri, 21 Jun 2024 00:32:02 -0400 Subject: [PATCH] refactor to more config based approach --- chainio/clients/elcontracts/reader.go | 58 +++++++++++++++++++++++++ chainio/utils/bindings.go | 62 +++++++++++++++++++++++++++ types/config.go | 8 ++++ 3 files changed, 128 insertions(+) create mode 100644 types/config.go diff --git a/chainio/clients/elcontracts/reader.go b/chainio/clients/elcontracts/reader.go index 71067de7..d018ce9e 100644 --- a/chainio/clients/elcontracts/reader.go +++ b/chainio/clients/elcontracts/reader.go @@ -1,6 +1,7 @@ package elcontracts import ( + "errors" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -73,6 +74,7 @@ type ELChainReader struct { // forces EthReader to implement the chainio.Reader interface var _ ELReader = (*ELChainReader)(nil) +// TODO(madhur): make this private. All clients should use build functions func NewELChainReader( slasher slasher.ContractISlasherCalls, delegationManager delegationmanager.ContractDelegationManagerCalls, @@ -116,7 +118,39 @@ func BuildELChainReader( ), nil } +type ElChainReaderConfig struct { + delegationManagerAddress gethcommon.Address + avsDirectoryAddress gethcommon.Address +} + +func BuildELChainReaderFromConfig( + cfg types.ElChainReaderConfig, + ethClient eth.Client, + logger logging.Logger, +) (*ELChainReader, error) { + elContractBindings, err := chainioutils.NewEigenLayerContractBindingsFromConfig( + cfg, + ethClient, + logger, + ) + if err != nil { + return nil, err + } + return NewELChainReader( + elContractBindings.Slasher, + elContractBindings.DelegationManager, + elContractBindings.StrategyManager, + elContractBindings.AvsDirectory, + logger, + ethClient, + ), nil +} + func (r *ELChainReader) IsOperatorRegistered(opts *bind.CallOpts, operator types.Operator) (bool, error) { + if r.delegationManager == nil { + return false, errors.New("DelegationManager contract not provided") + } + isOperator, err := r.delegationManager.IsOperator( opts, gethcommon.HexToAddress(operator.Address), @@ -129,6 +163,10 @@ func (r *ELChainReader) IsOperatorRegistered(opts *bind.CallOpts, operator types } func (r *ELChainReader) GetOperatorDetails(opts *bind.CallOpts, operator types.Operator) (types.Operator, error) { + if r.delegationManager == nil { + return types.Operator{}, errors.New("DelegationManager contract not provided") + } + operatorDetails, err := r.delegationManager.OperatorDetails( opts, gethcommon.HexToAddress(operator.Address), @@ -185,6 +223,10 @@ func (r *ELChainReader) ServiceManagerCanSlashOperatorUntilBlock( operatorAddr gethcommon.Address, serviceManagerAddr gethcommon.Address, ) (uint32, error) { + if r.slasher == nil { + return uint32(0), errors.New("slasher contract not provided") + } + serviceManagerCanSlashOperatorUntilBlock, err := r.slasher.ContractCanSlashOperatorUntilBlock( opts, operatorAddr, serviceManagerAddr, ) @@ -195,6 +237,10 @@ func (r *ELChainReader) ServiceManagerCanSlashOperatorUntilBlock( } func (r *ELChainReader) OperatorIsFrozen(opts *bind.CallOpts, operatorAddr gethcommon.Address) (bool, error) { + if r.slasher == nil { + return false, errors.New("slasher contract not provided") + } + operatorIsFrozen, err := r.slasher.IsFrozen(opts, operatorAddr) if err != nil { return false, err @@ -207,6 +253,10 @@ func (r *ELChainReader) GetOperatorSharesInStrategy( operatorAddr gethcommon.Address, strategyAddr gethcommon.Address, ) (*big.Int, error) { + if r.delegationManager == nil { + return &big.Int{}, errors.New("DelegationManager contract not provided") + } + operatorSharesInStrategy, err := r.delegationManager.OperatorShares( opts, operatorAddr, @@ -222,6 +272,10 @@ func (r *ELChainReader) CalculateDelegationApprovalDigestHash( opts *bind.CallOpts, staker gethcommon.Address, operator gethcommon.Address, delegationApprover gethcommon.Address, approverSalt [32]byte, expiry *big.Int, ) ([32]byte, error) { + if r.delegationManager == nil { + return [32]byte{}, errors.New("DelegationManager contract not provided") + } + return r.delegationManager.CalculateDelegationApprovalDigestHash( opts, staker, operator, delegationApprover, approverSalt, expiry, ) @@ -230,6 +284,10 @@ func (r *ELChainReader) CalculateDelegationApprovalDigestHash( func (r *ELChainReader) CalculateOperatorAVSRegistrationDigestHash( opts *bind.CallOpts, operator gethcommon.Address, avs gethcommon.Address, salt [32]byte, expiry *big.Int, ) ([32]byte, error) { + if r.avsDirectory == nil { + return [32]byte{}, errors.New("AVSDirectory contract not provided") + } + return r.avsDirectory.CalculateOperatorAVSRegistrationDigestHash( opts, operator, avs, salt, expiry, ) diff --git a/chainio/utils/bindings.go b/chainio/utils/bindings.go index 6097aaee..2d4a2320 100644 --- a/chainio/utils/bindings.go +++ b/chainio/utils/bindings.go @@ -4,6 +4,7 @@ package utils import ( "github.com/Layr-Labs/eigensdk-go/logging" + "github.com/Layr-Labs/eigensdk-go/types" "github.com/Layr-Labs/eigensdk-go/utils" "github.com/ethereum/go-ethereum/accounts/abi/bind" gethcommon "github.com/ethereum/go-ethereum/common" @@ -34,6 +35,67 @@ type EigenlayerContractBindings struct { AvsDirectory *avsdirectory.ContractAVSDirectory } +func NewEigenLayerContractBindingsFromConfig( + cfg types.ElChainReaderConfig, + client eth.Client, + logger logging.Logger, +) (*EigenlayerContractBindings, error) { + var contractDelegationManager *delegationmanager.ContractDelegationManager + var contractSlasher *slasher.ContractISlasher + var contractStrategyManager *strategymanager.ContractStrategyManager + var slasherAddr gethcommon.Address + var strategyManagerAddr gethcommon.Address + var avsDirectory *avsdirectory.ContractAVSDirectory + var err error + + if cfg.DelegationManagerAddress == gethcommon.HexToAddress("") { + logger.Warn("DelegationManager address not provided, the calls to the contract will not work") + } else { + contractDelegationManager, err = delegationmanager.NewContractDelegationManager(cfg.DelegationManagerAddress, client) + if err != nil { + return nil, utils.WrapError("Failed to create DelegationManager contract", err) + } + + slasherAddr, err = contractDelegationManager.Slasher(&bind.CallOpts{}) + if err != nil { + return nil, utils.WrapError("Failed to fetch Slasher address", err) + } + contractSlasher, err = slasher.NewContractISlasher(slasherAddr, client) + if err != nil { + return nil, utils.WrapError("Failed to fetch Slasher contract", err) + } + + strategyManagerAddr, err = contractDelegationManager.StrategyManager(&bind.CallOpts{}) + if err != nil { + return nil, utils.WrapError("Failed to fetch StrategyManager address", err) + } + contractStrategyManager, err = strategymanager.NewContractStrategyManager(strategyManagerAddr, client) + if err != nil { + return nil, utils.WrapError("Failed to fetch StrategyManager contract", err) + } + } + + if cfg.AvsDirectoryAddress == gethcommon.HexToAddress("") { + logger.Warn("AVSDirectory address not provided, the calls to the contract will not work") + } else { + avsDirectory, err = avsdirectory.NewContractAVSDirectory(cfg.AvsDirectoryAddress, client) + if err != nil { + return nil, utils.WrapError("Failed to fetch AVSDirectory contract", err) + } + } + + return &EigenlayerContractBindings{ + SlasherAddr: slasherAddr, + StrategyManagerAddr: strategyManagerAddr, + DelegationManagerAddr: cfg.DelegationManagerAddress, + AvsDirectoryAddr: cfg.AvsDirectoryAddress, + Slasher: contractSlasher, + StrategyManager: contractStrategyManager, + DelegationManager: contractDelegationManager, + AvsDirectory: avsDirectory, + }, nil +} + func NewEigenlayerContractBindings( delegationManagerAddr gethcommon.Address, avsDirectoryAddr gethcommon.Address, diff --git a/types/config.go b/types/config.go new file mode 100644 index 00000000..a3679d51 --- /dev/null +++ b/types/config.go @@ -0,0 +1,8 @@ +package types + +import "github.com/ethereum/go-ethereum/common" + +type ElChainReaderConfig struct { + DelegationManagerAddress common.Address + AvsDirectoryAddress common.Address +}