Skip to content

Commit

Permalink
[ELO-189] refactor el reader/writer to a config based approach (#278)
Browse files Browse the repository at this point in the history
* refactor to more config based approach

* remove unused type

* refactor based on disucssion

* add deprecated comment

* valid eth address check

* address comments

* delete file

* refactored writer
  • Loading branch information
shrimalmadhur authored Jun 26, 2024
1 parent bf693ea commit fcb5366
Show file tree
Hide file tree
Showing 5 changed files with 279 additions and 94 deletions.
Original file line number Diff line number Diff line change
@@ -1,88 +1,23 @@
// bindings.go contains functions that create contract bindings for the Eigenlayer and AVS contracts.
// These functions are meant to be used by constructors of the chainio package.
package utils
package avsregistry

import (
"github.com/Layr-Labs/eigensdk-go/logging"
"github.com/Layr-Labs/eigensdk-go/utils"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
gethcommon "github.com/ethereum/go-ethereum/common"

"github.com/Layr-Labs/eigensdk-go/chainio/clients/eth"
avsdirectory "github.com/Layr-Labs/eigensdk-go/contracts/bindings/AVSDirectory"
blsapkregistry "github.com/Layr-Labs/eigensdk-go/contracts/bindings/BLSApkRegistry"
delegationmanager "github.com/Layr-Labs/eigensdk-go/contracts/bindings/DelegationManager"
slasher "github.com/Layr-Labs/eigensdk-go/contracts/bindings/ISlasher"
indexregistry "github.com/Layr-Labs/eigensdk-go/contracts/bindings/IndexRegistry"
opstateretriever "github.com/Layr-Labs/eigensdk-go/contracts/bindings/OperatorStateRetriever"
regcoordinator "github.com/Layr-Labs/eigensdk-go/contracts/bindings/RegistryCoordinator"
servicemanager "github.com/Layr-Labs/eigensdk-go/contracts/bindings/ServiceManagerBase"
stakeregistry "github.com/Layr-Labs/eigensdk-go/contracts/bindings/StakeRegistry"
strategymanager "github.com/Layr-Labs/eigensdk-go/contracts/bindings/StrategyManager"
)

// Unclear to me why geth bindings don't store and expose the contract address...
// so we also store them here in case the different constructors that use this struct need them
type EigenlayerContractBindings struct {
SlasherAddr gethcommon.Address
StrategyManagerAddr gethcommon.Address
DelegationManagerAddr gethcommon.Address
AvsDirectoryAddr gethcommon.Address
Slasher *slasher.ContractISlasher
DelegationManager *delegationmanager.ContractDelegationManager
StrategyManager *strategymanager.ContractStrategyManager
AvsDirectory *avsdirectory.ContractAVSDirectory
}

func NewEigenlayerContractBindings(
delegationManagerAddr gethcommon.Address,
avsDirectoryAddr gethcommon.Address,
ethclient eth.Client,
logger logging.Logger,
) (*EigenlayerContractBindings, error) {
contractDelegationManager, err := delegationmanager.NewContractDelegationManager(delegationManagerAddr, ethclient)
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, ethclient)
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, ethclient)
if err != nil {
return nil, utils.WrapError("Failed to fetch StrategyManager contract", err)
}

avsDirectory, err := avsdirectory.NewContractAVSDirectory(avsDirectoryAddr, ethclient)
if err != nil {
return nil, utils.WrapError("Failed to fetch AVSDirectory contract", err)
}
"github.com/Layr-Labs/eigensdk-go/logging"
"github.com/Layr-Labs/eigensdk-go/utils"
"github.com/ethereum/go-ethereum/accounts/abi/bind"

return &EigenlayerContractBindings{
SlasherAddr: slasherAddr,
StrategyManagerAddr: strategyManagerAddr,
DelegationManagerAddr: delegationManagerAddr,
AvsDirectoryAddr: avsDirectoryAddr,
Slasher: contractSlasher,
StrategyManager: contractStrategyManager,
DelegationManager: contractDelegationManager,
AvsDirectory: avsDirectory,
}, nil
}
gethcommon "github.com/ethereum/go-ethereum/common"
)

// Unclear to me why geth bindings don't store and expose the contract address...
// ContractBindings Unclear to me why geth bindings don't store and expose the contract address...
// so we also store them here in case the different constructors that use this struct need them
type AvsRegistryContractBindings struct {
type ContractBindings struct {
// contract addresses
ServiceManagerAddr gethcommon.Address
RegistryCoordinatorAddr gethcommon.Address
Expand All @@ -104,7 +39,7 @@ func NewAVSRegistryContractBindings(
operatorStateRetrieverAddr gethcommon.Address,
ethclient eth.Client,
logger logging.Logger,
) (*AvsRegistryContractBindings, error) {
) (*ContractBindings, error) {
contractBlsRegistryCoordinator, err := regcoordinator.NewContractRegistryCoordinator(
registryCoordinatorAddr,
ethclient,
Expand Down Expand Up @@ -166,7 +101,7 @@ func NewAVSRegistryContractBindings(
return nil, utils.WrapError("Failed to fetch OperatorStateRetriever contract", err)
}

return &AvsRegistryContractBindings{
return &ContractBindings{
ServiceManagerAddr: serviceManagerAddr,
RegistryCoordinatorAddr: registryCoordinatorAddr,
StakeRegistryAddr: stakeregistryAddr,
Expand Down
23 changes: 11 additions & 12 deletions chainio/clients/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/Layr-Labs/eigensdk-go/chainio/clients/eth"
"github.com/Layr-Labs/eigensdk-go/chainio/clients/wallet"
"github.com/Layr-Labs/eigensdk-go/chainio/txmgr"
chainioutils "github.com/Layr-Labs/eigensdk-go/chainio/utils"
"github.com/Layr-Labs/eigensdk-go/logging"
"github.com/Layr-Labs/eigensdk-go/metrics"
"github.com/Layr-Labs/eigensdk-go/signerv2"
Expand Down Expand Up @@ -44,8 +43,8 @@ type Clients struct {
EthWsClient eth.Client
Wallet wallet.Wallet
TxManager txmgr.TxManager
AvsRegistryContractBindings *chainioutils.AvsRegistryContractBindings
EigenlayerContractBindings *chainioutils.EigenlayerContractBindings
AvsRegistryContractBindings *avsregistry.ContractBindings
EigenlayerContractBindings *elcontracts.ContractBindings
Metrics *metrics.EigenMetrics // exposes main avs node spec metrics that need to be incremented by avs code and used to start the metrics server
PrometheusRegistry *prometheus.Registry // Used if avs teams need to register avs-specific metrics
}
Expand Down Expand Up @@ -132,8 +131,8 @@ func BuildAll(
func (config *BuildAllConfig) buildAVSRegistryContractBindings(
ethHttpClient eth.Client,
logger logging.Logger,
) (*chainioutils.AvsRegistryContractBindings, error) {
avsRegistryContractBindings, err := chainioutils.NewAVSRegistryContractBindings(
) (*avsregistry.ContractBindings, error) {
avsRegistryContractBindings, err := avsregistry.NewAVSRegistryContractBindings(
gethcommon.HexToAddress(config.RegistryCoordinatorAddr),
gethcommon.HexToAddress(config.OperatorStateRetrieverAddr),
ethHttpClient,
Expand All @@ -149,16 +148,16 @@ func (config *BuildAllConfig) buildEigenLayerContractBindings(
delegationManagerAddr, avsDirectoryAddr gethcommon.Address,
ethHttpClient eth.Client,
logger logging.Logger,
) (*chainioutils.EigenlayerContractBindings, error) {
) (*elcontracts.ContractBindings, error) {

elContractBindings, err := chainioutils.NewEigenlayerContractBindings(
elContractBindings, err := elcontracts.NewEigenlayerContractBindings(
delegationManagerAddr,
avsDirectoryAddr,
ethHttpClient,
logger,
)
if err != nil {
return nil, utils.WrapError("Failed to create EigenlayerContractBindings", err)
return nil, utils.WrapError("Failed to create ContractBindings", err)
}
return elContractBindings, nil
}
Expand All @@ -168,7 +167,7 @@ func (config *BuildAllConfig) BuildELClients(
txMgr txmgr.TxManager,
logger logging.Logger,
eigenMetrics *metrics.EigenMetrics,
) (*elcontracts.ELChainReader, *elcontracts.ELChainWriter, *chainioutils.EigenlayerContractBindings, error) {
) (*elcontracts.ELChainReader, *elcontracts.ELChainWriter, *elcontracts.ContractBindings, error) {
avsRegistryContractBindings, err := config.buildAVSRegistryContractBindings(ethHttpClient, logger)
if err != nil {
return nil, nil, nil, err
Expand All @@ -190,7 +189,7 @@ func (config *BuildAllConfig) BuildELClients(
logger,
)
if err != nil {
return nil, nil, nil, utils.WrapError("Failed to create EigenlayerContractBindings", err)
return nil, nil, nil, utils.WrapError("Failed to create ContractBindings", err)
}

// get the Reader for the EL contracts
Expand Down Expand Up @@ -224,9 +223,9 @@ func (config *BuildAllConfig) BuildAVSRegistryClients(
ethWsClient eth.Client,
txMgr txmgr.TxManager,
logger logging.Logger,
) (*avsregistry.AvsRegistryChainReader, *avsregistry.AvsRegistryChainSubscriber, *avsregistry.AvsRegistryChainWriter, *chainioutils.AvsRegistryContractBindings, error) {
) (*avsregistry.AvsRegistryChainReader, *avsregistry.AvsRegistryChainSubscriber, *avsregistry.AvsRegistryChainWriter, *avsregistry.ContractBindings, error) {

avsRegistryContractBindings, err := chainioutils.NewAVSRegistryContractBindings(
avsRegistryContractBindings, err := avsregistry.NewAVSRegistryContractBindings(
gethcommon.HexToAddress(config.RegistryCoordinatorAddr),
gethcommon.HexToAddress(config.OperatorStateRetrieverAddr),
ethHttpClient,
Expand Down
140 changes: 140 additions & 0 deletions chainio/clients/elcontracts/bindings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Package elcontracts bindings.go contains functions that create contract bindings for the Eigenlayer Core contracts
// These functions are meant to be used by constructors of the chainio package.
package elcontracts

import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
gethcommon "github.com/ethereum/go-ethereum/common"

"github.com/Layr-Labs/eigensdk-go/chainio/clients/eth"
avsdirectory "github.com/Layr-Labs/eigensdk-go/contracts/bindings/AVSDirectory"
delegationmanager "github.com/Layr-Labs/eigensdk-go/contracts/bindings/DelegationManager"
slasher "github.com/Layr-Labs/eigensdk-go/contracts/bindings/ISlasher"
strategymanager "github.com/Layr-Labs/eigensdk-go/contracts/bindings/StrategyManager"
"github.com/Layr-Labs/eigensdk-go/logging"
"github.com/Layr-Labs/eigensdk-go/utils"
)

// ContractBindings contains the contract bindings for the EigenLayer Core contracts
//
// Unclear why geth bindings don't store and expose the contract address,
// so we also store them here in case the different constructors that use this struct need them
type ContractBindings struct {
SlasherAddr gethcommon.Address
StrategyManagerAddr gethcommon.Address
DelegationManagerAddr gethcommon.Address
AvsDirectoryAddr gethcommon.Address
Slasher *slasher.ContractISlasher
DelegationManager *delegationmanager.ContractDelegationManager
StrategyManager *strategymanager.ContractStrategyManager
AvsDirectory *avsdirectory.ContractAVSDirectory
}

func NewBindingsFromConfig(
cfg Config,
client eth.Client,
logger logging.Logger,
) (*ContractBindings, 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 gethcommon.IsHexAddress(cfg.DelegationManagerAddress.String()) {
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 gethcommon.IsHexAddress(cfg.AvsDirectoryAddress.String()) {
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 &ContractBindings{
SlasherAddr: slasherAddr,
StrategyManagerAddr: strategyManagerAddr,
DelegationManagerAddr: cfg.DelegationManagerAddress,
AvsDirectoryAddr: cfg.AvsDirectoryAddress,
Slasher: contractSlasher,
StrategyManager: contractStrategyManager,
DelegationManager: contractDelegationManager,
AvsDirectory: avsDirectory,
}, nil
}

// NewEigenlayerContractBindings creates a new ContractBindings struct with the provided contract addresses
// Deprecated: Use NewBindingsFromConfig instead
func NewEigenlayerContractBindings(
delegationManagerAddr gethcommon.Address,
avsDirectoryAddr gethcommon.Address,
ethclient eth.Client,
logger logging.Logger,
) (*ContractBindings, error) {
contractDelegationManager, err := delegationmanager.NewContractDelegationManager(delegationManagerAddr, ethclient)
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, ethclient)
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, ethclient)
if err != nil {
return nil, utils.WrapError("Failed to fetch StrategyManager contract", err)
}

avsDirectory, err := avsdirectory.NewContractAVSDirectory(avsDirectoryAddr, ethclient)
if err != nil {
return nil, utils.WrapError("Failed to fetch AVSDirectory contract", err)
}

return &ContractBindings{
SlasherAddr: slasherAddr,
StrategyManagerAddr: strategyManagerAddr,
DelegationManagerAddr: delegationManagerAddr,
AvsDirectoryAddr: avsDirectoryAddr,
Slasher: contractSlasher,
StrategyManager: contractStrategyManager,
DelegationManager: contractDelegationManager,
AvsDirectory: avsDirectory,
}, nil
}
Loading

0 comments on commit fcb5366

Please sign in to comment.