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: Rewards v2 release #260

Merged
merged 4 commits into from
Dec 13, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: set and get operator split command (#247)
gpabst committed Dec 13, 2024
commit 36b5a641f74fd3d394464b54fba2c91ad6d13d5d
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -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.20241211225219-79336bf6e886
github.com/blang/semver/v4 v4.0.0
github.com/consensys/gnark-crypto v0.12.1
github.com/ethereum/go-ethereum v1.14.5
@@ -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
@@ -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
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -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.20241211225219-79336bf6e886 h1:+7AijqdfRXdDc3zvj02Alqsk6Qd3owvlqPYQN1Hc1ME=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241211225219-79336bf6e886/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=
7 changes: 7 additions & 0 deletions pkg/internal/common/flags/general.go
Original file line number Diff line number Diff line change
@@ -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"},
2 changes: 2 additions & 0 deletions pkg/operator.go
Original file line number Diff line number Diff line change
@@ -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),
},
}

124 changes: 124 additions & 0 deletions pkg/operator/get_operator_split.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
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/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: getGetOperatorSplitFlags(),
}

return operatorSplitCmd
}

func getGetOperatorSplitFlags() []cli.Flag {
baseFlags := []cli.Flag{
&flags.NetworkFlag,
&flags.ETHRpcUrlFlag,
&flags.OperatorAddressFlag,
&split.OperatorSplitFlag,
&rewards.RewardsCoordinatorAddressFlag,
&split.AVSAddressFlag,
}

sort.Sort(cli.FlagsByName(baseFlags))
return baseFlags
}

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 {
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
}
202 changes: 202 additions & 0 deletions pkg/operator/set_operator_split.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
package operator

import (
"fmt"
"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/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: getSetOperatorSplitFlags(),
}

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

if config.Broadcast {

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...")

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)
} else {
noSendTxOpts := common.GetNoSendTxOpts(config.OperatorAddress)
_, _, contractBindings, err := elcontracts.BuildClients(elcontracts.Config{
RewardsCoordinatorAddress: config.RewardsCoordinatorAddress,
}, ethClient, nil, logger, nil)
if err != nil {
return err
}

code, err := ethClient.CodeAt(ctx, config.OperatorAddress, nil)
if err != nil {
return eigenSdkUtils.WrapError("failed to get code at address", err)
}
if len(code) > 0 {
// Operator is a smart contract
noSendTxOpts.GasLimit = 150_000
}

unsignedTx, err := contractBindings.RewardsCoordinator.SetOperatorAVSSplit(noSendTxOpts, config.OperatorAddress, config.AVSAddress, config.Split)

if err != nil {
return eigenSdkUtils.WrapError("failed to create unsigned tx", err)
}
if config.OutputType == string(common.OutputType_Calldata) {
calldataHex := gethcommon.Bytes2Hex(unsignedTx.Data())

if !common.IsEmptyString(config.OutputFile) {
err = common.WriteToFile([]byte(calldataHex), config.OutputFile)
if err != nil {
return err
}
logger.Infof("Call data written to file: %s", config.OutputFile)
} else {
fmt.Println(calldataHex)
}
} else {
logger.Infof("This transaction would set the operator split to %d", config.Split)
}

if !config.IsSilent {
txFeeDetails := common.GetTxFeeDetails(unsignedTx)
fmt.Println()
txFeeDetails.Print()

fmt.Println("To broadcast the operator set split, use the --broadcast flag")
}
}
return nil
}

func getSetOperatorSplitFlags() []cli.Flag {
baseFlags := []cli.Flag{
&flags.NetworkFlag,
&flags.ETHRpcUrlFlag,
&flags.OperatorAddressFlag,
&split.OperatorSplitFlag,
&rewards.RewardsCoordinatorAddressFlag,
&split.AVSAddressFlag,
&flags.BroadcastFlag,
&flags.OutputTypeFlag,
&flags.OutputFileFlag,
&flags.SilentFlag,
}

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)
broadcast := cCtx.Bool(flags.BroadcastFlag.Name)
outputType := cCtx.String(flags.OutputTypeFlag.Name)
outputFile := cCtx.String(flags.OutputFileFlag.Name)
isSilent := cCtx.Bool(flags.SilentFlag.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),
Broadcast: broadcast,
OutputType: outputType,
OutputFile: outputFile,
IsSilent: isSilent,
}, nil
}
Loading