Skip to content

Commit

Permalink
implement request-response pattern for GetSlashableShares and update …
Browse files Browse the repository at this point in the history
…tests.
  • Loading branch information
damiramirez committed Jan 23, 2025
1 parent 47a6e96 commit 6c6c782
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 35 deletions.
54 changes: 30 additions & 24 deletions chainio/clients/elcontracts/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

Expand Down Expand Up @@ -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
Expand Down
39 changes: 28 additions & 11 deletions chainio/clients/elcontracts/reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
},
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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{
Expand All @@ -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)
})
Expand Down
18 changes: 18 additions & 0 deletions chainio/clients/elcontracts/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,10 +286,28 @@ type GetOperatorsForOperatorSetResponse struct {
Operators []common.Address
}

type GetNumOperatorsForOperatorSetRequest struct {
OperatorSet allocationmanager.OperatorSet
}

type GetNumOperatorsForOperatorSetResponse struct {
NumOperators *big.Int
}

type GetStrategiesForOperatorSetRequest struct {
OperatorSet allocationmanager.OperatorSet
}

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
}

0 comments on commit 6c6c782

Please sign in to comment.