Skip to content

Commit 2c1c048

Browse files
bdchathamshrimalmadhur
authored andcommitted
Adding appointee remove and set command implementation and unit tests. (#250)
Co-authored-by: Brandon Chatham <[email protected]>
1 parent 54287d6 commit 2c1c048

File tree

12 files changed

+533
-12
lines changed

12 files changed

+533
-12
lines changed

cmd/eigenlayer/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func main() {
4343
app.Commands = append(app.Commands, pkg.RewardsCmd(prompter))
4444
app.Commands = append(app.Commands, pkg.KeysCmd(prompter))
4545
app.Commands = append(app.Commands, pkg.EigenPodCmd(prompter))
46-
app.Commands = append(app.Commands, pkg.UserCmd())
46+
app.Commands = append(app.Commands, pkg.UserCmd(prompter))
4747

4848
if err := app.Run(os.Args); err != nil {
4949
_, err := fmt.Fprintln(os.Stderr, err)

go.mod

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ require (
1010
//<<<<<<< HEAD
1111
// github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241212190947-9985122d81fe
1212
//=======
13-
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210000422-beb1a3c4502f
14-
//>>>>>>> 070a30e (feat: slashing commands)
13+
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210222107-c2ed40624db7
1514
github.com/blang/semver/v4 v4.0.0
1615
github.com/consensys/gnark-crypto v0.12.1
1716
github.com/ethereum/go-ethereum v1.14.5

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.12 h1:G5Q1SnLmFbEjhOkky3vIHk
1212
github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.12/go.mod h1:OlJd1QjqEW53wfWG/lJyPCGvrXwWVEjPQsP4TV+gttQ=
1313
github.com/Layr-Labs/eigenpod-proofs-generation v0.0.14-stable.0.20240730152248-5c11a259293e h1:DvW0/kWHV9mZsbH2KOjEHKTSIONNPUj6X05FJvUohy4=
1414
github.com/Layr-Labs/eigenpod-proofs-generation v0.0.14-stable.0.20240730152248-5c11a259293e/go.mod h1:T7tYN8bTdca2pkMnz9G2+ZwXYWw5gWqQUIu4KLgC/vM=
15-
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210000422-beb1a3c4502f h1:D94Vf+dALr9W0Ie18lZ8QDPvOAFX8FBbIpyVAtCUL1A=
16-
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210000422-beb1a3c4502f/go.mod h1:aYdNURUhaqeYOS+Cq12TfSdPbjFfiLaHkxPdR4Exq/s=
15+
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210222107-c2ed40624db7 h1:1kehcGgMyVloGzrd36CSibYz+fC2BkKV0fqeYCpovIQ=
16+
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241210222107-c2ed40624db7/go.mod h1:aYdNURUhaqeYOS+Cq12TfSdPbjFfiLaHkxPdR4Exq/s=
1717
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
1818
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
1919
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=

pkg/user/appointee/appointee.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ package appointee
33
import (
44
"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common/flags"
55
"github.com/Layr-Labs/eigenlayer-cli/pkg/telemetry"
6+
"github.com/Layr-Labs/eigenlayer-cli/pkg/utils"
67
"github.com/urfave/cli/v2"
78
)
89

9-
func AppointeeCmd() *cli.Command {
10+
func AppointeeCmd(prompter utils.Prompter) *cli.Command {
1011
appointeeCmd := &cli.Command{
1112
Name: "appointee",
1213
Usage: "user appointee <command>",
@@ -23,8 +24,8 @@ func AppointeeCmd() *cli.Command {
2324
canCallCmd(generateUserCanCallReader),
2425
ListCmd(generateListUsersReader),
2526
ListPermissionsCmd(generateListUserPermissionsReader),
26-
RemoveCmd(),
27-
SetCmd(),
27+
RemoveCmd(generateRemoveUserPermissionWriter(prompter)),
28+
SetCmd(generateSetUserPermissionWriter(prompter)),
2829
},
2930
}
3031

pkg/user/appointee/list_permissions_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/Layr-Labs/eigensdk-go/logging"
99
gethcommon "github.com/ethereum/go-ethereum/common"
1010
"github.com/stretchr/testify/assert"
11+
1112
"github.com/urfave/cli/v2"
1213
)
1314

pkg/user/appointee/list_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/Layr-Labs/eigensdk-go/logging"
99
gethcommon "github.com/ethereum/go-ethereum/common"
1010
"github.com/stretchr/testify/assert"
11+
1112
"github.com/urfave/cli/v2"
1213
)
1314

pkg/user/appointee/remove.go

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,31 @@
11
package appointee
22

33
import (
4+
"context"
45
"sort"
56

7+
"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common"
68
"github.com/Layr-Labs/eigenlayer-cli/pkg/internal/common/flags"
79
"github.com/Layr-Labs/eigenlayer-cli/pkg/telemetry"
10+
"github.com/Layr-Labs/eigenlayer-cli/pkg/utils"
11+
"github.com/Layr-Labs/eigensdk-go/chainio/clients/elcontracts"
12+
"github.com/Layr-Labs/eigensdk-go/logging"
13+
eigenSdkUtils "github.com/Layr-Labs/eigensdk-go/utils"
14+
gethcommon "github.com/ethereum/go-ethereum/common"
15+
gethtypes "github.com/ethereum/go-ethereum/core/types"
16+
"github.com/ethereum/go-ethereum/ethclient"
17+
818
"github.com/urfave/cli/v2"
919
)
1020

11-
func RemoveCmd() *cli.Command {
21+
type RemoveUserPermissionWriter interface {
22+
RemovePermission(
23+
ctx context.Context,
24+
request elcontracts.RemovePermissionRequest,
25+
) (*gethtypes.Receipt, error)
26+
}
27+
28+
func RemoveCmd(readerGenerator func(logging.Logger, *removeConfig) (RemoveUserPermissionWriter, error)) *cli.Command {
1229
removeCmd := &cli.Command{
1330
Name: "remove",
1431
Usage: "user appointee remove --account-address <AccountAddress> --appointee-address <AppointeeAddress> --target-address <TargetAddress> --selector <Selector>",
@@ -17,19 +34,140 @@ func RemoveCmd() *cli.Command {
1734
Remove a user's permission'.
1835
`,
1936
After: telemetry.AfterRunAction(),
37+
Action: func(c *cli.Context) error {
38+
return removeUserPermission(c, readerGenerator)
39+
},
2040
Flags: removeCommandFlags(),
2141
}
2242

2343
return removeCmd
2444
}
2545

46+
func removeUserPermission(
47+
cliCtx *cli.Context,
48+
generator func(logging.Logger, *removeConfig) (RemoveUserPermissionWriter, error),
49+
) error {
50+
ctx := cliCtx.Context
51+
logger := common.GetLogger(cliCtx)
52+
53+
config, err := readAndValidateRemoveConfig(cliCtx, logger)
54+
if err != nil {
55+
return eigenSdkUtils.WrapError("failed to read and validate user can call config", err)
56+
}
57+
cliCtx.App.Metadata["network"] = config.ChainID.String()
58+
permissionWriter, err := generator(logger, config)
59+
if err != nil {
60+
return err
61+
}
62+
receipt, err := permissionWriter.RemovePermission(
63+
ctx,
64+
elcontracts.RemovePermissionRequest{
65+
Account: config.AccountAddress,
66+
UserAddress: config.UserAddress,
67+
Target: config.Target,
68+
Selector: config.Selector,
69+
WaitForReceipt: true,
70+
},
71+
)
72+
if err != nil {
73+
return err
74+
}
75+
common.PrintTransactionInfo(receipt.TxHash.String(), config.ChainID)
76+
return nil
77+
}
78+
79+
func generateRemoveUserPermissionWriter(
80+
prompter utils.Prompter,
81+
) func(
82+
logger logging.Logger,
83+
config *removeConfig,
84+
) (RemoveUserPermissionWriter, error) {
85+
return func(logger logging.Logger, config *removeConfig) (RemoveUserPermissionWriter, error) {
86+
ethClient, err := ethclient.Dial(config.RPCUrl)
87+
if err != nil {
88+
return nil, eigenSdkUtils.WrapError("failed to create new eth client", err)
89+
}
90+
elWriter, err := common.GetELWriter(
91+
config.AccountAddress,
92+
&config.SignerConfig,
93+
ethClient,
94+
elcontracts.Config{
95+
PermissionsControllerAddress: config.PermissionManagerAddress,
96+
},
97+
prompter,
98+
config.ChainID,
99+
logger,
100+
)
101+
return elWriter, err
102+
}
103+
}
104+
105+
func readAndValidateRemoveConfig(cliContext *cli.Context, logger logging.Logger) (*removeConfig, error) {
106+
accountAddress := gethcommon.HexToAddress(cliContext.String(AccountAddressFlag.Name))
107+
userAddress := gethcommon.HexToAddress(cliContext.String(AppointeeAddressFlag.Name))
108+
ethRpcUrl := cliContext.String(flags.ETHRpcUrlFlag.Name)
109+
network := cliContext.String(flags.NetworkFlag.Name)
110+
environment := cliContext.String(flags.EnvironmentFlag.Name)
111+
target := gethcommon.HexToAddress(cliContext.String(TargetAddressFlag.Name))
112+
selector := cliContext.String(SelectorFlag.Name)
113+
selectorBytes, err := common.ValidateAndConvertSelectorString(selector)
114+
if err != nil {
115+
return nil, err
116+
}
117+
signerConfig, err := common.GetSignerConfig(cliContext, logger)
118+
if err != nil {
119+
// We don't want to throw error since people can still use it to generate the claim
120+
// without broadcasting it
121+
logger.Debugf("Failed to get signer config: %s", err)
122+
}
123+
124+
if environment == "" {
125+
environment = common.GetEnvFromNetwork(network)
126+
}
127+
128+
chainID := utils.NetworkNameToChainId(network)
129+
cliContext.App.Metadata["network"] = chainID.String()
130+
permissionManagerAddress := cliContext.String(PermissionControllerAddressFlag.Name)
131+
132+
if common.IsEmptyString(permissionManagerAddress) {
133+
permissionManagerAddress, err = common.GetPermissionManagerAddress(utils.NetworkNameToChainId(network))
134+
if err != nil {
135+
return nil, err
136+
}
137+
}
138+
139+
logger.Debugf(
140+
"Env: %s, network: %s, chain ID: %s, PermissionManager address: %s",
141+
environment,
142+
network,
143+
chainID,
144+
permissionManagerAddress,
145+
)
146+
147+
return &removeConfig{
148+
Network: network,
149+
RPCUrl: ethRpcUrl,
150+
AccountAddress: accountAddress,
151+
UserAddress: userAddress,
152+
Target: target,
153+
Selector: selectorBytes,
154+
SignerConfig: *signerConfig,
155+
PermissionManagerAddress: gethcommon.HexToAddress(permissionManagerAddress),
156+
ChainID: chainID,
157+
Environment: environment,
158+
}, nil
159+
}
160+
26161
func removeCommandFlags() []cli.Flag {
27162
cmdFlags := []cli.Flag{
28163
&flags.VerboseFlag,
29164
&AccountAddressFlag,
30165
&AppointeeAddressFlag,
31166
&TargetAddressFlag,
32167
&SelectorFlag,
168+
&flags.NetworkFlag,
169+
&flags.EnvironmentFlag,
170+
&flags.ETHRpcUrlFlag,
33171
}
34172
sort.Sort(cli.FlagsByName(cmdFlags))
35173
return append(cmdFlags, flags.GetSignerFlags()...)

pkg/user/appointee/remove_test.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package appointee
2+
3+
import (
4+
"context"
5+
"errors"
6+
gethtypes "github.com/ethereum/go-ethereum/core/types"
7+
"testing"
8+
9+
"github.com/Layr-Labs/eigensdk-go/chainio/clients/elcontracts"
10+
"github.com/Layr-Labs/eigensdk-go/logging"
11+
"github.com/stretchr/testify/assert"
12+
13+
"github.com/urfave/cli/v2"
14+
)
15+
16+
type mockRemoveUserPermissionWriter struct {
17+
removePermissionFunc func(ctx context.Context, request elcontracts.RemovePermissionRequest) (*gethtypes.Receipt, error)
18+
}
19+
20+
func (m *mockRemoveUserPermissionWriter) RemovePermission(
21+
ctx context.Context,
22+
request elcontracts.RemovePermissionRequest,
23+
) (*gethtypes.Receipt, error) {
24+
return m.removePermissionFunc(ctx, request)
25+
}
26+
27+
func generateMockRemoveWriter(err error) func(logging.Logger, *removeConfig) (RemoveUserPermissionWriter, error) {
28+
return func(logger logging.Logger, config *removeConfig) (RemoveUserPermissionWriter, error) {
29+
return &mockRemoveUserPermissionWriter{
30+
removePermissionFunc: func(ctx context.Context, request elcontracts.RemovePermissionRequest) (*gethtypes.Receipt, error) {
31+
return &gethtypes.Receipt{}, err
32+
},
33+
}, nil
34+
}
35+
}
36+
37+
func TestRemoveCmd_Success(t *testing.T) {
38+
app := cli.NewApp()
39+
app.Commands = []*cli.Command{
40+
RemoveCmd(generateMockRemoveWriter(nil)),
41+
}
42+
43+
args := []string{
44+
"TestRemoveCmd_Success",
45+
"remove",
46+
"--account-address", "0x1234567890abcdef1234567890abcdef12345678",
47+
"--appointee-address", "0xabcdef1234567890abcdef1234567890abcdef12",
48+
"--target-address", "0x9876543210fedcba9876543210fedcba98765432",
49+
"--selector", "0x1A2B3C4D",
50+
"--network", "holesky",
51+
"--eth-rpc-url", "https://ethereum-holesky.publicnode.com/",
52+
"--ecdsa-private-key", "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
53+
}
54+
55+
err := app.Run(args)
56+
assert.NoError(t, err)
57+
}
58+
59+
func TestRemoveCmd_GeneratorError(t *testing.T) {
60+
expectedError := "failed to create permission writer"
61+
app := cli.NewApp()
62+
app.Commands = []*cli.Command{
63+
RemoveCmd(func(logger logging.Logger, config *removeConfig) (RemoveUserPermissionWriter, error) {
64+
return nil, errors.New(expectedError)
65+
}),
66+
}
67+
68+
args := []string{
69+
"TestRemoveCmd_GeneratorError",
70+
"remove",
71+
"--account-address", "0x1234567890abcdef1234567890abcdef12345678",
72+
"--appointee-address", "0xabcdef1234567890abcdef1234567890abcdef12",
73+
"--target-address", "0x9876543210fedcba9876543210fedcba98765432",
74+
"--selector", "0x1A2B3C4D",
75+
"--network", "holesky",
76+
"--eth-rpc-url", "https://ethereum-holesky.publicnode.com/",
77+
"--ecdsa-private-key", "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
78+
}
79+
80+
err := app.Run(args)
81+
assert.Error(t, err)
82+
assert.Contains(t, err.Error(), expectedError)
83+
}
84+
85+
func TestRemoveCmd_RemovePermissionError(t *testing.T) {
86+
expectedError := "error removing permission"
87+
app := cli.NewApp()
88+
app.Commands = []*cli.Command{
89+
RemoveCmd(generateMockRemoveWriter(errors.New(expectedError))),
90+
}
91+
92+
args := []string{
93+
"TestRemoveCmd_RemovePermissionError",
94+
"remove",
95+
"--account-address", "0x1234567890abcdef1234567890abcdef12345678",
96+
"--appointee-address", "0xabcdef1234567890abcdef1234567890abcdef12",
97+
"--target-address", "0x9876543210fedcba9876543210fedcba98765432",
98+
"--selector", "0x1A2B3C4D",
99+
"--network", "holesky",
100+
"--eth-rpc-url", "https://ethereum-holesky.publicnode.com/",
101+
"--ecdsa-private-key", "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
102+
"--path-to-key-store", "/path/to/keystore.json",
103+
}
104+
105+
err := app.Run(args)
106+
assert.Error(t, err)
107+
assert.Contains(t, err.Error(), expectedError)
108+
}

0 commit comments

Comments
 (0)