Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: set and get operator split command #247

Merged
merged 13 commits into from
Dec 12, 2024
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/Layr-Labs/eigenlayer-contracts v0.3.2-mainnet-rewards
github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.12
github.com/Layr-Labs/eigenpod-proofs-generation v0.0.14-stable.0.20240730152248-5c11a259293e
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241121204729-7d2cd162ffe8
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241209163655-6b1cbb153ef6
github.com/blang/semver/v4 v4.0.0
github.com/consensys/gnark-crypto v0.12.1
github.com/ethereum/go-ethereum v1.14.5
Expand All @@ -19,6 +19,7 @@ require (
github.com/tyler-smith/go-bip39 v1.1.0
github.com/urfave/cli/v2 v2.27.2
github.com/wagslane/go-password-validator v0.3.0
github.com/wealdtech/go-merkletree/v2 v2.5.2-0.20240302222400-69219c450662
github.com/wk8/go-ordered-map/v2 v2.1.8
go.uber.org/mock v0.4.0
gopkg.in/yaml.v2 v2.4.0
Expand Down Expand Up @@ -100,7 +101,6 @@ require (
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/wealdtech/go-merkletree/v2 v2.5.2-0.20240302222400-69219c450662 // indirect
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
Expand Down
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.12 h1:G5Q1SnLmFbEjhOkky3vIHk
github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.12/go.mod h1:OlJd1QjqEW53wfWG/lJyPCGvrXwWVEjPQsP4TV+gttQ=
github.com/Layr-Labs/eigenpod-proofs-generation v0.0.14-stable.0.20240730152248-5c11a259293e h1:DvW0/kWHV9mZsbH2KOjEHKTSIONNPUj6X05FJvUohy4=
github.com/Layr-Labs/eigenpod-proofs-generation v0.0.14-stable.0.20240730152248-5c11a259293e/go.mod h1:T7tYN8bTdca2pkMnz9G2+ZwXYWw5gWqQUIu4KLgC/vM=
github.com/Layr-Labs/eigensdk-go v0.1.13-0.20241023200243-565bb4438918 h1:Itl141PoMFzq58ZTo4Nu/CyH+x8f4BH6OmBNhZ6Z2/I=
github.com/Layr-Labs/eigensdk-go v0.1.13-0.20241023200243-565bb4438918/go.mod h1:aYdNURUhaqeYOS+Cq12TfSdPbjFfiLaHkxPdR4Exq/s=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241121204729-7d2cd162ffe8 h1:6wuVq+Elto+yF7bQ3QYqD2psxGXR3wcJh2koNcUjIQM=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241121204729-7d2cd162ffe8/go.mod h1:aYdNURUhaqeYOS+Cq12TfSdPbjFfiLaHkxPdR4Exq/s=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241209163655-6b1cbb153ef6 h1:qQk3QJ+I+ffHOpZvaEC1NULxl3Hfzi+ojpniBAmUdWg=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241209163655-6b1cbb153ef6/go.mod h1:aYdNURUhaqeYOS+Cq12TfSdPbjFfiLaHkxPdR4Exq/s=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
Expand Down
7 changes: 7 additions & 0 deletions pkg/internal/common/flags/general.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ var (
Value: 3600,
}

OperatorAddressFlag = cli.StringFlag{
Name: "operator-address",
Aliases: []string{"oa", "operator"},
Usage: "Operator address",
EnvVars: []string{"OPERATOR_ADDRESS"},
}

BatchClaimFile = cli.StringFlag{
Name: "batch-claim-file",
Aliases: []string{"bcf"},
Expand Down
2 changes: 2 additions & 0 deletions pkg/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ func OperatorCmd(p utils.Prompter) *cli.Command {
operator.UpdateCmd(p),
operator.UpdateMetadataURICmd(p),
operator.GetApprovalCmd(p),
operator.SetOperatorSplitCmd(p),
operator.GetOperatorSplitCmd(p),
},
}

Expand Down
108 changes: 108 additions & 0 deletions pkg/operator/get_operator_split.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package operator

import (
"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common"
"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common/flags"
"github.com/Layr-Labs/eigenlayer-cli/pkg/operator/split"
"github.com/Layr-Labs/eigenlayer-cli/pkg/rewards"
"github.com/Layr-Labs/eigenlayer-cli/pkg/telemetry"
"github.com/Layr-Labs/eigenlayer-cli/pkg/utils"
"github.com/Layr-Labs/eigensdk-go/chainio/clients/elcontracts"
"github.com/Layr-Labs/eigensdk-go/logging"
eigenSdkUtils "github.com/Layr-Labs/eigensdk-go/utils"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/urfave/cli/v2"
)

func GetOperatorSplitCmd(p utils.Prompter) *cli.Command {
var operatorSplitCmd = &cli.Command{
Name: "get-rewards-split",
Usage: "Get operator rewards split",
Action: func(cCtx *cli.Context) error {
return GetOperatorSplit(cCtx)
},
After: telemetry.AfterRunAction(),
Flags: getOperatorSplitFlags(),
gpabst marked this conversation as resolved.
Show resolved Hide resolved
}

return operatorSplitCmd
}

func GetOperatorSplit(cCtx *cli.Context) error {
ctx := cCtx.Context
logger := common.GetLogger(cCtx)

config, err := readAndValidateGetOperatorSplitConfig(cCtx, logger)
if err != nil {
return eigenSdkUtils.WrapError("failed to read and validate operator split config", err)
}

cCtx.App.Metadata["network"] = config.ChainID.String()

ethClient, err := ethclient.Dial(config.RPCUrl)
if err != nil {
return eigenSdkUtils.WrapError("failed to create new eth client", err)
}

elReader, err := elcontracts.NewReaderFromConfig(
elcontracts.Config{
RewardsCoordinatorAddress: config.RewardsCoordinatorAddress,
},
ethClient,
logger,
)

if err != nil {
return eigenSdkUtils.WrapError("failed to get EL writer", err)
}

logger.Infof("Getting operator split...")

split, err := elReader.GetOperatorAVSSplit(ctx, config.OperatorAddress, config.AVSAddress)

if err != nil || split == nil {
return eigenSdkUtils.WrapError("failed to get operator split", err)
}

logger.Infof("Operator split is %d", *split)

return nil
}

func readAndValidateGetOperatorSplitConfig(
cCtx *cli.Context,
logger logging.Logger,
) (*split.GetOperatorAVSSplitConfig, error) {
network := cCtx.String(flags.NetworkFlag.Name)
rpcUrl := cCtx.String(flags.ETHRpcUrlFlag.Name)

rewardsCoordinatorAddress := cCtx.String(rewards.RewardsCoordinatorAddressFlag.Name)

var err error
if common.IsEmptyString(rewardsCoordinatorAddress) {
rewardsCoordinatorAddress, err = common.GetRewardCoordinatorAddress(utils.NetworkNameToChainId(network))
if err != nil {
return nil, err
}
}
logger.Debugf("Using Rewards Coordinator address: %s", rewardsCoordinatorAddress)

operatorAddress := gethcommon.HexToAddress(cCtx.String(flags.OperatorAddressFlag.Name))
logger.Infof("Using operator address: %s", operatorAddress.String())

avsAddress := gethcommon.HexToAddress(cCtx.String(split.AVSAddressFlag.Name))
logger.Infof("Using AVS address: %s", avsAddress.String())

chainID := utils.NetworkNameToChainId(network)
logger.Debugf("Using chain ID: %s", chainID.String())

return &split.GetOperatorAVSSplitConfig{
Network: network,
RPCUrl: rpcUrl,
RewardsCoordinatorAddress: gethcommon.HexToAddress(rewardsCoordinatorAddress),
ChainID: chainID,
OperatorAddress: operatorAddress,
AVSAddress: avsAddress,
}, nil
}
143 changes: 143 additions & 0 deletions pkg/operator/set_operator_split.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package operator

import (
"sort"

"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common"
"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common/flags"
"github.com/Layr-Labs/eigenlayer-cli/pkg/operator/split"
"github.com/Layr-Labs/eigenlayer-cli/pkg/rewards"
"github.com/Layr-Labs/eigenlayer-cli/pkg/telemetry"
"github.com/Layr-Labs/eigenlayer-cli/pkg/utils"
"github.com/Layr-Labs/eigensdk-go/chainio/clients/elcontracts"
"github.com/Layr-Labs/eigensdk-go/logging"
eigenSdkUtils "github.com/Layr-Labs/eigensdk-go/utils"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/urfave/cli/v2"
)

func SetOperatorSplitCmd(p utils.Prompter) *cli.Command {
var operatorSplitCmd = &cli.Command{
Name: "set-rewards-split",
Usage: "Set operator rewards split",
Action: func(cCtx *cli.Context) error {
return SetOperatorSplit(cCtx, p)
},
After: telemetry.AfterRunAction(),
Flags: getOperatorSplitFlags(),
}

return operatorSplitCmd
}

func SetOperatorSplit(cCtx *cli.Context, p utils.Prompter) error {
ctx := cCtx.Context
logger := common.GetLogger(cCtx)

config, err := readAndValidateSetOperatorSplitConfig(cCtx, logger)
if err != nil {
return eigenSdkUtils.WrapError("failed to read and validate operator split config", err)
}

cCtx.App.Metadata["network"] = config.ChainID.String()

ethClient, err := ethclient.Dial(config.RPCUrl)
if err != nil {
return eigenSdkUtils.WrapError("failed to create new eth client", err)
}

eLWriter, err := common.GetELWriter(
config.OperatorAddress,
config.SignerConfig,
ethClient,
elcontracts.Config{
RewardsCoordinatorAddress: config.RewardsCoordinatorAddress,
},
p,
config.ChainID,
logger,
)

if err != nil {
return eigenSdkUtils.WrapError("failed to get EL writer", err)
}

logger.Infof("Broadcasting set operator transaction...")

var receipt *types.Receipt

receipt, err = eLWriter.SetOperatorAVSSplit(ctx, config.OperatorAddress, config.AVSAddress, config.Split, true)

if err != nil {
return eigenSdkUtils.WrapError("failed to process claim", err)
}

logger.Infof("Set operator transaction submitted successfully")
common.PrintTransactionInfo(receipt.TxHash.String(), config.ChainID)

return nil
}

func getOperatorSplitFlags() []cli.Flag {
baseFlags := []cli.Flag{
&flags.NetworkFlag,
gpabst marked this conversation as resolved.
Show resolved Hide resolved
&flags.ETHRpcUrlFlag,
&flags.OperatorAddressFlag,
&split.OperatorSplitFlag,
&rewards.RewardsCoordinatorAddressFlag,
&split.AVSAddressFlag,
}

allFlags := append(baseFlags, flags.GetSignerFlags()...)
sort.Sort(cli.FlagsByName(allFlags))
return allFlags
}

func readAndValidateSetOperatorSplitConfig(
cCtx *cli.Context,
logger logging.Logger,
) (*split.SetOperatorAVSSplitConfig, error) {
network := cCtx.String(flags.NetworkFlag.Name)
rpcUrl := cCtx.String(flags.ETHRpcUrlFlag.Name)
opSplit := cCtx.Int(split.OperatorSplitFlag.Name)
rewardsCoordinatorAddress := cCtx.String(rewards.RewardsCoordinatorAddressFlag.Name)

var err error
if common.IsEmptyString(rewardsCoordinatorAddress) {
rewardsCoordinatorAddress, err = common.GetRewardCoordinatorAddress(utils.NetworkNameToChainId(network))
if err != nil {
return nil, err
}
}
logger.Debugf("Using Rewards Coordinator address: %s", rewardsCoordinatorAddress)

operatorAddress := gethcommon.HexToAddress(cCtx.String(flags.OperatorAddressFlag.Name))
logger.Infof("Using operator address: %s", operatorAddress.String())

avsAddress := gethcommon.HexToAddress(cCtx.String(split.AVSAddressFlag.Name))
logger.Infof("Using AVS address: %s", avsAddress.String())

chainID := utils.NetworkNameToChainId(network)
logger.Debugf("Using chain ID: %s", chainID.String())

// Get SignerConfig
signerConfig, err := common.GetSignerConfig(cCtx, logger)
if err != nil {
// We don't want to throw error since people can still use it to generate the claim
// without broadcasting it
logger.Debugf("Failed to get signer config: %s", err)
}

return &split.SetOperatorAVSSplitConfig{
Network: network,
RPCUrl: rpcUrl,
RewardsCoordinatorAddress: gethcommon.HexToAddress(rewardsCoordinatorAddress),
ChainID: chainID,
SignerConfig: signerConfig,
OperatorAddress: operatorAddress,
AVSAddress: avsAddress,
Split: uint16(opSplit),
}, nil
}
20 changes: 20 additions & 0 deletions pkg/operator/split/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package split

import "github.com/urfave/cli/v2"

var (
OperatorSplitFlag = cli.IntFlag{
Name: "operator-split",
Aliases: []string{"os"},
Usage: "Split for the operator in bips (e.g. 1000 = 10%)",
Required: false,
EnvVars: []string{"OPERATOR_SPLIT"},
}

AVSAddressFlag = cli.StringFlag{
Name: "avs-address",
Aliases: []string{"aa"},
Usage: "AVS address to set operator split",
EnvVars: []string{"AVS_ADDRESS"},
}
)
30 changes: 30 additions & 0 deletions pkg/operator/split/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package split

import (
"math/big"

"github.com/Layr-Labs/eigenlayer-cli/pkg/types"
gethcommon "github.com/ethereum/go-ethereum/common"
)

type SetOperatorAVSSplitConfig struct {
Network string
RPCUrl string
RewardsCoordinatorAddress gethcommon.Address
ChainID *big.Int
SignerConfig *types.SignerConfig

OperatorAddress gethcommon.Address
AVSAddress gethcommon.Address
Split uint16
}

type GetOperatorAVSSplitConfig struct {
Network string
RPCUrl string
RewardsCoordinatorAddress gethcommon.Address
ChainID *big.Int

OperatorAddress gethcommon.Address
AVSAddress gethcommon.Address
}
Loading