Skip to content

Commit

Permalink
feat: add create slashable stake quorum func (#531)
Browse files Browse the repository at this point in the history
  • Loading branch information
maximopalopoli authored Feb 7, 2025
1 parent 3abf50b commit 2cbfd15
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 3 deletions.
37 changes: 37 additions & 0 deletions chainio/clients/avsregistry/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,43 @@ func (w *ChainWriter) SetSlashableStakeLookahead(
return receipt, nil
}

// Creates a new quorum that tracks slashable stake for operators.
// It receives the operator set parameters for the given quorum, the minimum stake required to register,
// and the number of blocks to look ahead when calculating slashable stake.
// Returns the transaction receipt in case of success.
// Note: This function does not work on M2 AVSs.
func (w *ChainWriter) CreateSlashableStakeQuorum(
ctx context.Context,
operatorSetParams regcoord.ISlashingRegistryCoordinatorTypesOperatorSetParam,
minimumStakeRequired *big.Int,
strategyParams []regcoord.IStakeRegistryTypesStrategyParams,
lookAheadPeriod uint32,
waitForReceipt bool,
) (*gethtypes.Receipt, error) {
w.logger.Info("Creating slashable stake quorum")

noSendTxOpts, err := w.txMgr.GetNoSendTxOpts()
if err != nil {
return nil, err
}

tx, err := w.registryCoordinator.CreateSlashableStakeQuorum(
noSendTxOpts,
operatorSetParams,
minimumStakeRequired,
strategyParams,
lookAheadPeriod,
)
if err != nil {
return nil, err
}
receipt, err := w.txMgr.Send(ctx, tx, waitForReceipt)
if err != nil {
return nil, utils.WrapError("failed to send CreateSlashableStakeQuorum tx with err", err.Error())
}
return receipt, nil
}

// Receives an operator address and quorum numbers and ejects the operator from the given quorums.
// Note: if the operator is not registered, the call will not fail, but will do nothing.
func (w *ChainWriter) EjectOperator(
Expand Down
73 changes: 70 additions & 3 deletions chainio/clients/avsregistry/writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package avsregistry_test

import (
"context"
"math/big"
"testing"

"github.com/Layr-Labs/eigensdk-go/chainio/clients/avsregistry"
chainioutils "github.com/Layr-Labs/eigensdk-go/chainio/utils"
regcoordinator "github.com/Layr-Labs/eigensdk-go/contracts/bindings/RegistryCoordinator"
regcoord "github.com/Layr-Labs/eigensdk-go/contracts/bindings/RegistryCoordinator"
servicemanager "github.com/Layr-Labs/eigensdk-go/contracts/bindings/ServiceManagerBase"
stakeregistry "github.com/Layr-Labs/eigensdk-go/contracts/bindings/StakeRegistry"
"github.com/Layr-Labs/eigensdk-go/crypto/bls"
Expand Down Expand Up @@ -135,7 +136,7 @@ func TestWriterMethods(t *testing.T) {
ethHttpClient, err := ethclient.Dial(anvilHttpEndpoint)
require.NoError(t, err)

contractBlsRegistryCoordinator, err := regcoordinator.NewContractRegistryCoordinator(
contractBlsRegistryCoordinator, err := regcoord.NewContractRegistryCoordinator(
contractAddrs.RegistryCoordinator,
ethHttpClient,
)
Expand Down Expand Up @@ -256,7 +257,8 @@ func TestWriterMethods(t *testing.T) {
ethHttpClient, err := ethclient.Dial(anvilHttpEndpoint)
require.NoError(t, err)

contractBlsRegistryCoordinator, err := regcoordinator.NewContractRegistryCoordinator(
contractBlsRegistryCoordinator, err := regcoord.NewContractRegistryCoordinator(

contractAddrs.RegistryCoordinator,
ethHttpClient,
)
Expand Down Expand Up @@ -329,6 +331,71 @@ func TestBlsSignature(t *testing.T) {
assert.Equal(t, y, "4960450323239587206117776989095741074887370703941588742100855592356200866613")
}

func TestCreateSlashableStakeQuorum(t *testing.T) {
// Test set up
clients, anvilHttpEndpoint := testclients.BuildTestClients(t)
chainReader := clients.ReadClients.AvsRegistryChainReader

contractAddrs := testutils.GetContractAddressesFromContractRegistry(anvilHttpEndpoint)

chainWriter := clients.AvsRegistryChainWriter

// Beyond MaxOperatorCount, the other params are not used anywhere other than in registerOperatorWithChurn
operatorSetParams := regcoord.ISlashingRegistryCoordinatorTypesOperatorSetParam{
MaxOperatorCount: 192,
KickBIPsOfOperatorStake: 0,
KickBIPsOfTotalStake: 0,
}
minimumStakeNeeded := big.NewInt(0)

strategyAddr := contractAddrs.Erc20MockStrategy
strategyParam := regcoord.IStakeRegistryTypesStrategyParams{
Strategy: strategyAddr,
Multiplier: big.NewInt(1e18),
}

lookAheadPeriod := uint32(0)

// First, quorum count is 1 because Registry is initialized with 1 quorum
count, err := chainReader.GetQuorumCount(&bind.CallOpts{})
require.NoError(t, err)
assert.Equal(t, count, uint8(1))

registryCoordinatorAddress := contractAddrs.RegistryCoordinator
registryCoordinator, err := regcoord.NewContractRegistryCoordinator(
registryCoordinatorAddress,
clients.EthHttpClient,
)
require.NoError(t, err)

txManager := clients.TxManager
noSendTxOpts, err := txManager.GetNoSendTxOpts()
require.NoError(t, err)

tx, err := registryCoordinator.EnableOperatorSets(noSendTxOpts)
require.NoError(t, err)

_, err = txManager.Send(context.Background(), tx, true)
require.NoError(t, err)

// Create a new slashable stake quorum
receipt, err := chainWriter.CreateSlashableStakeQuorum(
context.Background(),
operatorSetParams,
minimumStakeNeeded,
[]regcoord.IStakeRegistryTypesStrategyParams{strategyParam},
lookAheadPeriod,
true,
)
require.NoError(t, err)
require.Equal(t, receipt.Status, gethtypes.ReceiptStatusSuccessful)

// After creating a new one, quorum count is 2
count, err = chainReader.GetQuorumCount(&bind.CallOpts{})
require.NoError(t, err)
assert.Equal(t, count, uint8(2))
}

func TestEjectOperator(t *testing.T) {
// Test set up
clients, _ := testclients.BuildTestClients(t)
Expand Down

0 comments on commit 2cbfd15

Please sign in to comment.