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
2 changes: 2 additions & 0 deletions pkg/rewards.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ func RewardsCmd(p utils.Prompter) *cli.Command {
rewards.ClaimCmd(p),
rewards.SetClaimerCmd(p),
rewards.ShowCmd(p),
rewards.SetOperatorSplitCmd(p),
rewards.GetOperatorSplitCmd(p),
},
}

Expand Down
18 changes: 17 additions & 1 deletion pkg/rewards/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ var (

AVSAddressesFlag = cli.StringFlag{
Name: "avs-addresses",
Aliases: []string{"a"},
Aliases: []string{"aa"},
Usage: "Comma seperated addresses of the AVS",
EnvVars: []string{"AVS_ADDRESSES"},
}
Expand All @@ -91,4 +91,20 @@ var (
Value: "all",
EnvVars: []string{"REWARDS_CLAIM_TYPE"},
}

OperatorAddressFlag = cli.StringFlag{
Name: "operator-address",
Aliases: []string{"a"},
gpabst marked this conversation as resolved.
Show resolved Hide resolved
Usage: "Address of the operator",
Required: false,
EnvVars: []string{"REWARDS_OPERATOR_ADDRESS"},
gpabst marked this conversation as resolved.
Show resolved Hide resolved
}

OperatorSplitFlag = cli.IntFlag{
Name: "operator-split",
Aliases: []string{"os"},
Usage: "Split for the operator in bips (e.g. 1000 = 10%)",
Required: false,
EnvVars: []string{"REWARDS_OPERATOR_SPLIT"},
}
)
225 changes: 225 additions & 0 deletions pkg/rewards/operator_split.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
package rewards

import (
"errors"
"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/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-operator-split",
Usage: "Set operator split",
Action: func(cCtx *cli.Context) error {
return SetOperatorSplit(cCtx, p)
},
After: telemetry.AfterRunAction(),
Flags: getOperatorSplitFlags(),
}

return operatorSplitCmd
}

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

return operatorSplitCmd
}
gpabst marked this conversation as resolved.
Show resolved Hide resolved

func GetOperatorSplit(cCtx *cli.Context, p utils.Prompter) error {
gpabst marked this conversation as resolved.
Show resolved Hide resolved
ctx := cCtx.Context
logger := common.GetLogger(cCtx)

config, err := readAndValidateOperatorSplitConfig(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 SetOperatorSplit(cCtx *cli.Context, p utils.Prompter) error {
ctx := cCtx.Context
logger := common.GetLogger(cCtx)

config, err := readAndValidateOperatorSplitConfig(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 readAndValidateOperatorSplitConfig(cCtx *cli.Context, logger logging.Logger) (*SetOperatorAVSSplitConfig, error) {
network := cCtx.String(flags.NetworkFlag.Name)
environment := cCtx.String(EnvironmentFlag.Name)
rpcUrl := cCtx.String(flags.ETHRpcUrlFlag.Name)
broadcast := cCtx.Bool(flags.BroadcastFlag.Name)
split := cCtx.Int(OperatorSplitFlag.Name)
rewardsCoordinatorAddress := cCtx.String(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)

claimTimestamp := cCtx.String(ClaimTimestampFlag.Name)
logger.Debugf("Using claim timestamp from user: %s", claimTimestamp)
gpabst marked this conversation as resolved.
Show resolved Hide resolved

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

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

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

proofStoreBaseURL := cCtx.String(ProofStoreBaseURLFlag.Name)

// If empty get from utils
if common.IsEmptyString(proofStoreBaseURL) {
proofStoreBaseURL = getProofStoreBaseURL(network)

// If still empty return error
if common.IsEmptyString(proofStoreBaseURL) {
return nil, errors.New("proof store base URL not provided")
}
}
logger.Debugf("Using Proof store base URL: %s", proofStoreBaseURL)
gpabst marked this conversation as resolved.
Show resolved Hide resolved

if common.IsEmptyString(environment) {
environment = getEnvFromNetwork(network)
}
logger.Debugf("Using network %s and environment: %s", network, environment)

// 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)
}

// TODO(shrimalmadhur): Fix to make sure correct S3 bucket is used. Clean up later
if network == utils.MainnetNetworkName {
network = "ethereum"
}
gpabst marked this conversation as resolved.
Show resolved Hide resolved

return &SetOperatorAVSSplitConfig{
Network: network,
RPCUrl: rpcUrl,
Broadcast: broadcast,
RewardsCoordinatorAddress: gethcommon.HexToAddress(rewardsCoordinatorAddress),
ChainID: chainID,
SignerConfig: signerConfig,
OperatorAddress: operatorAddress,
AVSAddress: avsAddress,
Split: uint16(split),
}, nil
}

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

allFlags := append(baseFlags, flags.GetSignerFlags()...)
sort.Sort(cli.FlagsByName(allFlags))
return allFlags
}
12 changes: 12 additions & 0 deletions pkg/rewards/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ type rewardsJson struct {

type allRewardsJson []rewardsJson

type SetOperatorAVSSplitConfig struct {
gpabst marked this conversation as resolved.
Show resolved Hide resolved
Network string
RPCUrl string
Broadcast bool
RewardsCoordinatorAddress gethcommon.Address
ChainID *big.Int
SignerConfig *types.SignerConfig

OperatorAddress gethcommon.Address
AVSAddress gethcommon.Address
Split uint16
}
gpabst marked this conversation as resolved.
Show resolved Hide resolved
type ClaimConfig struct {
Network string
RPCUrl string
Expand Down
Loading