From 6c6c782e201580327df2560e4e9db1e77078d973 Mon Sep 17 00:00:00 2001 From: Damian Ramirez Date: Thu, 23 Jan 2025 18:02:04 -0300 Subject: [PATCH] implement request-response pattern for GetSlashableShares and update tests. --- chainio/clients/elcontracts/reader.go | 54 ++++++++++++---------- chainio/clients/elcontracts/reader_test.go | 39 +++++++++++----- chainio/clients/elcontracts/types.go | 18 ++++++++ 3 files changed, 76 insertions(+), 35 deletions(-) diff --git a/chainio/clients/elcontracts/reader.go b/chainio/clients/elcontracts/reader.go index de59d389..761fa56b 100644 --- a/chainio/clients/elcontracts/reader.go +++ b/chainio/clients/elcontracts/reader.go @@ -698,16 +698,22 @@ func (r *ChainReader) GetOperatorsForOperatorSet( // GetNumOperatorsForOperatorSet returns the number of operators in a specific operator set func (r *ChainReader) GetNumOperatorsForOperatorSet( ctx context.Context, - operatorSet allocationmanager.OperatorSet, -) (*big.Int, error) { - if operatorSet.Id == 0 { - return nil, errLegacyAVSsNotSupported + blockNumber *big.Int, + request GetNumOperatorsForOperatorSetRequest, +) (GetNumOperatorsForOperatorSetResponse, error) { + if request.OperatorSet.Id == 0 { + return GetNumOperatorsForOperatorSetResponse{}, errLegacyAVSsNotSupported } else { if r.allocationManager == nil { - return nil, errors.New("AllocationManager contract not provided") + return GetNumOperatorsForOperatorSetResponse{}, errors.New("AllocationManager contract not provided") + } + + memberCount, err := r.allocationManager.GetMemberCount(&bind.CallOpts{Context: ctx, BlockNumber: blockNumber}, request.OperatorSet) + if err != nil { + return GetNumOperatorsForOperatorSetResponse{}, utils.WrapError("failed to get member count", err) } - return r.allocationManager.GetMemberCount(&bind.CallOpts{Context: ctx}, operatorSet) + return GetNumOperatorsForOperatorSetResponse{NumOperators: memberCount}, nil } } @@ -739,42 +745,42 @@ func (r *ChainReader) GetStrategiesForOperatorSet( func (r *ChainReader) GetSlashableShares( ctx context.Context, - operatorAddress gethcommon.Address, - operatorSet allocationmanager.OperatorSet, - strategies []gethcommon.Address, -) (map[gethcommon.Address]*big.Int, error) { + blockNumber *big.Int, + request GetSlashableSharesRequest, +) (GetSlashableSharesResponse, error) { if r.allocationManager == nil { - return nil, errors.New("AllocationManager contract not provided") + return GetSlashableSharesResponse{}, errors.New("AllocationManager contract not provided") } - currentBlock, err := r.ethClient.BlockNumber(ctx) + // TODO: Is necessary to get the block number here? Or should we use the one passed as argument? + // currentBlock, err := r.ethClient.BlockNumber(ctx) // This call should not fail since it's a getter - if err != nil { - return nil, err - } + // if err != nil { + // return GetSlashableSharesResponse{}, err + // } slashableShares, err := r.allocationManager.GetMinimumSlashableStake( - &bind.CallOpts{Context: ctx}, - operatorSet, - []gethcommon.Address{operatorAddress}, - strategies, - uint32(currentBlock), + &bind.CallOpts{Context: ctx, BlockNumber: blockNumber}, + request.OperatorSet, + []gethcommon.Address{request.OperatorAddress}, + request.StrategiesAddresses, + uint32(blockNumber.Uint64()), ) // This call should not fail since it's a getter if err != nil { - return nil, err + return GetSlashableSharesResponse{}, err } if len(slashableShares) == 0 { - return nil, errors.New("no slashable shares found for operator") + return GetSlashableSharesResponse{}, errors.New("no slashable shares found for operator") } slashableShareStrategyMap := make(map[gethcommon.Address]*big.Int) - for i, strat := range strategies { + for i, strat := range request.StrategiesAddresses { // The reason we use 0 here is because we only have one operator in the list slashableShareStrategyMap[strat] = slashableShares[0][i] } - return slashableShareStrategyMap, nil + return GetSlashableSharesResponse{SlashableShares: slashableShareStrategyMap}, nil } // GetSlashableSharesForOperatorSets returns the strategies the operatorSets take into account, their diff --git a/chainio/clients/elcontracts/reader_test.go b/chainio/clients/elcontracts/reader_test.go index 5d5a80ee..a8ecaaa0 100644 --- a/chainio/clients/elcontracts/reader_test.go +++ b/chainio/clients/elcontracts/reader_test.go @@ -1143,9 +1143,13 @@ func TestInvalidConfig(t *testing.T) { Avs: testAddr, Id: operatorSetId, } + request := elcontracts.GetNumOperatorsForOperatorSetRequest{ + OperatorSet: operatorSet, + } _, err := chainReader.GetNumOperatorsForOperatorSet( context.Background(), - operatorSet, + nil, + request, ) require.Error(t, err) }, @@ -1312,19 +1316,26 @@ func TestOperatorSetsAndSlashableShares(t *testing.T) { }) t.Run("get amount of operators for operatorsets", func(t *testing.T) { - operatorsCount, err := chainReader.GetNumOperatorsForOperatorSet(context.Background(), operatorSet) + request := elcontracts.GetNumOperatorsForOperatorSetRequest{ + OperatorSet: operatorSet, + } + response, err := chainReader.GetNumOperatorsForOperatorSet(context.Background(), nil, request) require.NoError(t, err) - require.NotZero(t, operatorsCount) + require.NotZero(t, response.NumOperators) }) }) t.Run("slashable shares tests", func(t *testing.T) { + request := elcontracts.GetSlashableSharesRequest{ + OperatorAddress: operatorAddr, + OperatorSet: operatorSet, + StrategiesAddresses: strategies, + } t.Run("get slashable shares for single operator", func(t *testing.T) { shares, err := chainReader.GetSlashableShares( context.Background(), - operatorAddr, - operatorSet, - strategies, + receipt.BlockNumber, + request, ) require.NoError(t, err) require.NotEmpty(t, shares) @@ -1374,7 +1385,10 @@ func TestOperatorSetsWithWrongInput(t *testing.T) { _, err := chainReader.GetOperatorsForOperatorSet(ctx, nil, request) require.Error(t, err) - _, err = chainReader.GetNumOperatorsForOperatorSet(ctx, operatorSet) + requestNumOps := elcontracts.GetNumOperatorsForOperatorSetRequest{ + OperatorSet: operatorSet, + } + _, err = chainReader.GetNumOperatorsForOperatorSet(ctx, nil, requestNumOps) require.Error(t, err) requestStr := elcontracts.GetStrategiesForOperatorSetRequest{ @@ -1384,12 +1398,15 @@ func TestOperatorSetsWithWrongInput(t *testing.T) { require.Error(t, err) strategies := []common.Address{contractAddrs.Erc20MockStrategy} - + requestSlashable := elcontracts.GetSlashableSharesRequest{ + OperatorAddress: operatorAddr, + OperatorSet: operatorSet, + StrategiesAddresses: strategies, + } _, err = chainReader.GetSlashableShares( ctx, - operatorAddr, - operatorSet, - strategies, + nil, + requestSlashable, ) require.Error(t, err) }) diff --git a/chainio/clients/elcontracts/types.go b/chainio/clients/elcontracts/types.go index a36fda22..3945bbac 100644 --- a/chainio/clients/elcontracts/types.go +++ b/chainio/clients/elcontracts/types.go @@ -286,6 +286,14 @@ type GetOperatorsForOperatorSetResponse struct { Operators []common.Address } +type GetNumOperatorsForOperatorSetRequest struct { + OperatorSet allocationmanager.OperatorSet +} + +type GetNumOperatorsForOperatorSetResponse struct { + NumOperators *big.Int +} + type GetStrategiesForOperatorSetRequest struct { OperatorSet allocationmanager.OperatorSet } @@ -293,3 +301,13 @@ type GetStrategiesForOperatorSetRequest struct { type GetStrategiesForOperatorSetResponse struct { StrategiesAddresses []common.Address } + +type GetSlashableSharesRequest struct { + OperatorAddress common.Address + OperatorSet allocationmanager.OperatorSet + StrategiesAddresses []common.Address +} + +type GetSlashableSharesResponse struct { + SlashableShares map[common.Address]*big.Int +}