Skip to content

Commit

Permalink
Adding appointee remove and set command implementation and unit…
Browse files Browse the repository at this point in the history
… tests. (#250)

Co-authored-by: Brandon Chatham <[email protected]>
  • Loading branch information
2 people authored and shrimalmadhur committed Dec 16, 2024
1 parent 54287d6 commit 2c1c048
Show file tree
Hide file tree
Showing 12 changed files with 533 additions and 12 deletions.
2 changes: 1 addition & 1 deletion cmd/eigenlayer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func main() {
app.Commands = append(app.Commands, pkg.RewardsCmd(prompter))
app.Commands = append(app.Commands, pkg.KeysCmd(prompter))
app.Commands = append(app.Commands, pkg.EigenPodCmd(prompter))
app.Commands = append(app.Commands, pkg.UserCmd())
app.Commands = append(app.Commands, pkg.UserCmd(prompter))

if err := app.Run(os.Args); err != nil {
_, err := fmt.Fprintln(os.Stderr, err)
Expand Down
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ require (
//<<<<<<< HEAD
// github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241212190947-9985122d81fe
//=======
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210000422-beb1a3c4502f
//>>>>>>> 070a30e (feat: slashing commands)
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210222107-c2ed40624db7
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 Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +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.14-0.20241210000422-beb1a3c4502f h1:D94Vf+dALr9W0Ie18lZ8QDPvOAFX8FBbIpyVAtCUL1A=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210000422-beb1a3c4502f/go.mod h1:aYdNURUhaqeYOS+Cq12TfSdPbjFfiLaHkxPdR4Exq/s=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210222107-c2ed40624db7 h1:1kehcGgMyVloGzrd36CSibYz+fC2BkKV0fqeYCpovIQ=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210222107-c2ed40624db7/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: 4 additions & 3 deletions pkg/user/appointee/appointee.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package appointee
import (
"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/urfave/cli/v2"
)

func AppointeeCmd() *cli.Command {
func AppointeeCmd(prompter utils.Prompter) *cli.Command {
appointeeCmd := &cli.Command{
Name: "appointee",
Usage: "user appointee <command>",
Expand All @@ -23,8 +24,8 @@ func AppointeeCmd() *cli.Command {
canCallCmd(generateUserCanCallReader),
ListCmd(generateListUsersReader),
ListPermissionsCmd(generateListUserPermissionsReader),
RemoveCmd(),
SetCmd(),
RemoveCmd(generateRemoveUserPermissionWriter(prompter)),
SetCmd(generateSetUserPermissionWriter(prompter)),
},
}

Expand Down
1 change: 1 addition & 0 deletions pkg/user/appointee/list_permissions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/Layr-Labs/eigensdk-go/logging"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/assert"

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

Expand Down
1 change: 1 addition & 0 deletions pkg/user/appointee/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/Layr-Labs/eigensdk-go/logging"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/assert"

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

Expand Down
140 changes: 139 additions & 1 deletion pkg/user/appointee/remove.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
package appointee

import (
"context"
"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"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"

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

func RemoveCmd() *cli.Command {
type RemoveUserPermissionWriter interface {
RemovePermission(
ctx context.Context,
request elcontracts.RemovePermissionRequest,
) (*gethtypes.Receipt, error)
}

func RemoveCmd(readerGenerator func(logging.Logger, *removeConfig) (RemoveUserPermissionWriter, error)) *cli.Command {
removeCmd := &cli.Command{
Name: "remove",
Usage: "user appointee remove --account-address <AccountAddress> --appointee-address <AppointeeAddress> --target-address <TargetAddress> --selector <Selector>",
Expand All @@ -17,19 +34,140 @@ func RemoveCmd() *cli.Command {
Remove a user's permission'.
`,
After: telemetry.AfterRunAction(),
Action: func(c *cli.Context) error {
return removeUserPermission(c, readerGenerator)
},
Flags: removeCommandFlags(),
}

return removeCmd
}

func removeUserPermission(
cliCtx *cli.Context,
generator func(logging.Logger, *removeConfig) (RemoveUserPermissionWriter, error),
) error {
ctx := cliCtx.Context
logger := common.GetLogger(cliCtx)

config, err := readAndValidateRemoveConfig(cliCtx, logger)
if err != nil {
return eigenSdkUtils.WrapError("failed to read and validate user can call config", err)
}
cliCtx.App.Metadata["network"] = config.ChainID.String()
permissionWriter, err := generator(logger, config)
if err != nil {
return err
}
receipt, err := permissionWriter.RemovePermission(
ctx,
elcontracts.RemovePermissionRequest{
Account: config.AccountAddress,
UserAddress: config.UserAddress,
Target: config.Target,
Selector: config.Selector,
WaitForReceipt: true,
},
)
if err != nil {
return err
}
common.PrintTransactionInfo(receipt.TxHash.String(), config.ChainID)
return nil
}

func generateRemoveUserPermissionWriter(
prompter utils.Prompter,
) func(
logger logging.Logger,
config *removeConfig,
) (RemoveUserPermissionWriter, error) {
return func(logger logging.Logger, config *removeConfig) (RemoveUserPermissionWriter, error) {
ethClient, err := ethclient.Dial(config.RPCUrl)
if err != nil {
return nil, eigenSdkUtils.WrapError("failed to create new eth client", err)
}
elWriter, err := common.GetELWriter(
config.AccountAddress,
&config.SignerConfig,
ethClient,
elcontracts.Config{
PermissionsControllerAddress: config.PermissionManagerAddress,
},
prompter,
config.ChainID,
logger,
)
return elWriter, err
}
}

func readAndValidateRemoveConfig(cliContext *cli.Context, logger logging.Logger) (*removeConfig, error) {
accountAddress := gethcommon.HexToAddress(cliContext.String(AccountAddressFlag.Name))
userAddress := gethcommon.HexToAddress(cliContext.String(AppointeeAddressFlag.Name))
ethRpcUrl := cliContext.String(flags.ETHRpcUrlFlag.Name)
network := cliContext.String(flags.NetworkFlag.Name)
environment := cliContext.String(flags.EnvironmentFlag.Name)
target := gethcommon.HexToAddress(cliContext.String(TargetAddressFlag.Name))
selector := cliContext.String(SelectorFlag.Name)
selectorBytes, err := common.ValidateAndConvertSelectorString(selector)
if err != nil {
return nil, err
}
signerConfig, err := common.GetSignerConfig(cliContext, 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)
}

if environment == "" {
environment = common.GetEnvFromNetwork(network)
}

chainID := utils.NetworkNameToChainId(network)
cliContext.App.Metadata["network"] = chainID.String()
permissionManagerAddress := cliContext.String(PermissionControllerAddressFlag.Name)

if common.IsEmptyString(permissionManagerAddress) {
permissionManagerAddress, err = common.GetPermissionManagerAddress(utils.NetworkNameToChainId(network))
if err != nil {
return nil, err
}
}

logger.Debugf(
"Env: %s, network: %s, chain ID: %s, PermissionManager address: %s",
environment,
network,
chainID,
permissionManagerAddress,
)

return &removeConfig{
Network: network,
RPCUrl: ethRpcUrl,
AccountAddress: accountAddress,
UserAddress: userAddress,
Target: target,
Selector: selectorBytes,
SignerConfig: *signerConfig,
PermissionManagerAddress: gethcommon.HexToAddress(permissionManagerAddress),
ChainID: chainID,
Environment: environment,
}, nil
}

func removeCommandFlags() []cli.Flag {
cmdFlags := []cli.Flag{
&flags.VerboseFlag,
&AccountAddressFlag,
&AppointeeAddressFlag,
&TargetAddressFlag,
&SelectorFlag,
&flags.NetworkFlag,
&flags.EnvironmentFlag,
&flags.ETHRpcUrlFlag,
}
sort.Sort(cli.FlagsByName(cmdFlags))
return append(cmdFlags, flags.GetSignerFlags()...)
Expand Down
108 changes: 108 additions & 0 deletions pkg/user/appointee/remove_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package appointee

import (
"context"
"errors"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"testing"

"github.com/Layr-Labs/eigensdk-go/chainio/clients/elcontracts"
"github.com/Layr-Labs/eigensdk-go/logging"
"github.com/stretchr/testify/assert"

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

type mockRemoveUserPermissionWriter struct {
removePermissionFunc func(ctx context.Context, request elcontracts.RemovePermissionRequest) (*gethtypes.Receipt, error)
}

func (m *mockRemoveUserPermissionWriter) RemovePermission(
ctx context.Context,
request elcontracts.RemovePermissionRequest,
) (*gethtypes.Receipt, error) {
return m.removePermissionFunc(ctx, request)
}

func generateMockRemoveWriter(err error) func(logging.Logger, *removeConfig) (RemoveUserPermissionWriter, error) {
return func(logger logging.Logger, config *removeConfig) (RemoveUserPermissionWriter, error) {
return &mockRemoveUserPermissionWriter{
removePermissionFunc: func(ctx context.Context, request elcontracts.RemovePermissionRequest) (*gethtypes.Receipt, error) {
return &gethtypes.Receipt{}, err
},
}, nil
}
}

func TestRemoveCmd_Success(t *testing.T) {
app := cli.NewApp()
app.Commands = []*cli.Command{
RemoveCmd(generateMockRemoveWriter(nil)),
}

args := []string{
"TestRemoveCmd_Success",
"remove",
"--account-address", "0x1234567890abcdef1234567890abcdef12345678",
"--appointee-address", "0xabcdef1234567890abcdef1234567890abcdef12",
"--target-address", "0x9876543210fedcba9876543210fedcba98765432",
"--selector", "0x1A2B3C4D",
"--network", "holesky",
"--eth-rpc-url", "https://ethereum-holesky.publicnode.com/",
"--ecdsa-private-key", "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
}

err := app.Run(args)
assert.NoError(t, err)
}

func TestRemoveCmd_GeneratorError(t *testing.T) {
expectedError := "failed to create permission writer"
app := cli.NewApp()
app.Commands = []*cli.Command{
RemoveCmd(func(logger logging.Logger, config *removeConfig) (RemoveUserPermissionWriter, error) {
return nil, errors.New(expectedError)
}),
}

args := []string{
"TestRemoveCmd_GeneratorError",
"remove",
"--account-address", "0x1234567890abcdef1234567890abcdef12345678",
"--appointee-address", "0xabcdef1234567890abcdef1234567890abcdef12",
"--target-address", "0x9876543210fedcba9876543210fedcba98765432",
"--selector", "0x1A2B3C4D",
"--network", "holesky",
"--eth-rpc-url", "https://ethereum-holesky.publicnode.com/",
"--ecdsa-private-key", "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
}

err := app.Run(args)
assert.Error(t, err)
assert.Contains(t, err.Error(), expectedError)
}

func TestRemoveCmd_RemovePermissionError(t *testing.T) {
expectedError := "error removing permission"
app := cli.NewApp()
app.Commands = []*cli.Command{
RemoveCmd(generateMockRemoveWriter(errors.New(expectedError))),
}

args := []string{
"TestRemoveCmd_RemovePermissionError",
"remove",
"--account-address", "0x1234567890abcdef1234567890abcdef12345678",
"--appointee-address", "0xabcdef1234567890abcdef1234567890abcdef12",
"--target-address", "0x9876543210fedcba9876543210fedcba98765432",
"--selector", "0x1A2B3C4D",
"--network", "holesky",
"--eth-rpc-url", "https://ethereum-holesky.publicnode.com/",
"--ecdsa-private-key", "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
"--path-to-key-store", "/path/to/keystore.json",
}

err := app.Run(args)
assert.Error(t, err)
assert.Contains(t, err.Error(), expectedError)
}
Loading

0 comments on commit 2c1c048

Please sign in to comment.