Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AvsRegistry tests #360

Merged
merged 11 commits into from
Oct 4, 2024
180 changes: 180 additions & 0 deletions chainio/clients/avsregistry/reader_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package avsregistry_test

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

"github.com/Layr-Labs/eigensdk-go/chainio/clients"
"github.com/Layr-Labs/eigensdk-go/logging"
"github.com/Layr-Labs/eigensdk-go/testutils"
"github.com/Layr-Labs/eigensdk-go/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"
)

// Starts an anvil container and builds the ChainIO Clients for testing.
func BuildTestClients(t *testing.T) *clients.Clients {
testConfig := testutils.GetDefaultTestConfig()
anvilC, err := testutils.StartAnvilContainer(testConfig.AnvilStateFileName)
require.NoError(t, err)

anvilHttpEndpoint, err := anvilC.Endpoint(context.Background(), "http")
require.NoError(t, err)

anvilWsEndpoint, err := anvilC.Endpoint(context.Background(), "ws")
require.NoError(t, err)
logger := logging.NewTextSLogger(os.Stdout, &logging.SLoggerOptions{Level: testConfig.LogLevel})

privateKeyHex := "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
ecdsaPrivateKey, err := crypto.HexToECDSA(privateKeyHex)
require.NoError(t, err)

contractAddrs := testutils.GetContractAddressesFromContractRegistry(anvilHttpEndpoint)
require.NoError(t, err)

chainioConfig := clients.BuildAllConfig{
EthHttpUrl: anvilHttpEndpoint,
EthWsUrl: anvilWsEndpoint,
RegistryCoordinatorAddr: contractAddrs.RegistryCoordinator.String(),
OperatorStateRetrieverAddr: contractAddrs.OperatorStateRetriever.String(),
AvsName: "exampleAvs",
PromMetricsIpPortAddress: ":9090",
}

clients, err := clients.BuildAll(
chainioConfig,
ecdsaPrivateKey,
logger,
)
require.NoError(t, err)
return clients
}

func TestReaderMethods(t *testing.T) {
clients := BuildTestClients(t)
chainReader := clients.ReadClients.AvsRegistryChainReader

quorumNumbers := types.QuorumNums{0}

t.Run("get quorum state", func(t *testing.T) {
count, err := chainReader.GetQuorumCount(&bind.CallOpts{})
require.NoError(t, err)
require.NotNil(t, count)
})

t.Run("get operator stake in quorums at current block", func(t *testing.T) {
stake, err := chainReader.GetOperatorsStakeInQuorumsAtCurrentBlock(&bind.CallOpts{}, quorumNumbers)
require.NoError(t, err)
require.NotNil(t, stake)
})

t.Run("get operator stake in quorums at block", func(t *testing.T) {
stake, err := chainReader.GetOperatorsStakeInQuorumsAtBlock(&bind.CallOpts{}, quorumNumbers, 100)
require.NoError(t, err)
require.NotNil(t, stake)
})

t.Run("get operator address in quorums at current block", func(t *testing.T) {
addresses, err := chainReader.GetOperatorAddrsInQuorumsAtCurrentBlock(&bind.CallOpts{}, quorumNumbers)
require.NoError(t, err)
require.NotNil(t, addresses)
})

t.Run(
"get operators stake in quorums of operator at block returns error for non-registered operator",
func(t *testing.T) {
operatorAddress := common.Address{0x1}
operatorId, err := chainReader.GetOperatorId(&bind.CallOpts{}, operatorAddress)
require.NoError(t, err)

_, _, err = chainReader.GetOperatorsStakeInQuorumsOfOperatorAtBlock(&bind.CallOpts{}, operatorId, 100)
require.Error(t, err)
require.Contains(t, err.Error(), "Failed to get operators state")
})

t.Run(
"get single operator stake in quorums of operator at current block returns error for non-registered operator",
func(t *testing.T) {
operatorAddress := common.Address{0x1}
operatorId, err := chainReader.GetOperatorId(&bind.CallOpts{}, operatorAddress)
require.NoError(t, err)

stakes, err := chainReader.GetOperatorStakeInQuorumsOfOperatorAtCurrentBlock(&bind.CallOpts{}, operatorId)
require.NoError(t, err)
require.Equal(t, 0, len(stakes))
})

t.Run("get check signatures indices returns error for non-registered operator", func(t *testing.T) {
operatorAddress := common.Address{0x1}
operatorId, err := chainReader.GetOperatorId(&bind.CallOpts{}, operatorAddress)
require.NoError(t, err)

_, err = chainReader.GetCheckSignaturesIndices(
&bind.CallOpts{},
100,
quorumNumbers,
[]types.OperatorId{operatorId},
)
require.Contains(t, err.Error(), "Failed to get check signatures indices")
})

t.Run("get operator id", func(t *testing.T) {
operatorAddress := common.Address{0x1}
operatorId, err := chainReader.GetOperatorId(&bind.CallOpts{}, operatorAddress)
require.NoError(t, err)
require.NotNil(t, operatorId)
})

t.Run("get operator from id returns zero address for non-registered operator", func(t *testing.T) {
operatorAddress := common.HexToAddress("0x1234567890123456789012345678901234567890")
operatorId, err := chainReader.GetOperatorId(&bind.CallOpts{}, operatorAddress)
require.NoError(t, err)

retrievedAddress, err := chainReader.GetOperatorFromId(&bind.CallOpts{}, operatorId)
require.NoError(t, err)
require.Equal(t, retrievedAddress, common.Address{0x0})
})

t.Run("query registration detail", func(t *testing.T) {
operatorAddress := common.HexToAddress("0x1234567890123456789012345678901234567890")
quorums, err := chainReader.QueryRegistrationDetail(&bind.CallOpts{}, operatorAddress)
require.NoError(t, err)
require.Equal(t, 1, len(quorums))
})

t.Run("is operator registered", func(t *testing.T) {
operatorAddress := common.HexToAddress("0x1234567890123456789012345678901234567890")
isRegistered, err := chainReader.IsOperatorRegistered(&bind.CallOpts{}, operatorAddress)
require.NoError(t, err)
require.False(t, isRegistered)
})

t.Run(
"query existing registered operator pub keys", func(t *testing.T) {
addresses, pubKeys, err := chainReader.QueryExistingRegisteredOperatorPubKeys(
context.Background(),
big.NewInt(0),
nil,
nil,
)
require.NoError(t, err)
require.Equal(t, 0, len(pubKeys))
require.Equal(t, 0, len(addresses))
})

t.Run(
"query existing registered operator sockets", func(t *testing.T) {
address_to_sockets, err := chainReader.QueryExistingRegisteredOperatorSockets(
context.Background(),
big.NewInt(0),
nil,
nil,
)
require.NoError(t, err)
require.Equal(t, 0, len(address_to_sockets))
})
}
73 changes: 73 additions & 0 deletions chainio/clients/avsregistry/writer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package avsregistry_test

import (
"context"
"testing"

chainioutils "github.com/Layr-Labs/eigensdk-go/chainio/utils"
"github.com/Layr-Labs/eigensdk-go/crypto/bls"
"github.com/Layr-Labs/eigensdk-go/types"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"
)

func TestWriterMethods(t *testing.T) {
clients := BuildTestClients(t)
chainWriter := clients.AvsRegistryChainWriter

keypair, err := bls.NewKeyPairFromString("0x01")
require.NoError(t, err)

addr := gethcommon.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266")
ecdsaPrivKeyHex := "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
ecdsaPrivateKey, err := crypto.HexToECDSA(ecdsaPrivKeyHex)
require.NoError(t, err)

quorumNumbers := types.QuorumNums{0}

t.Run("register operator", func(t *testing.T) {
receipt, err := chainWriter.RegisterOperator(
context.Background(),
ecdsaPrivateKey,
keypair,
quorumNumbers,
"",
true,
)
require.NoError(t, err)
require.NotNil(t, receipt)
})

t.Run("update stake of operator subset", func(t *testing.T) {
receipt, err := chainWriter.UpdateStakesOfOperatorSubsetForAllQuorums(
context.Background(),
[]gethcommon.Address{addr},
true,
)
require.NoError(t, err)
require.NotNil(t, receipt)
})

t.Run("update stake of entire operator set", func(t *testing.T) {
receipt, err := chainWriter.UpdateStakesOfEntireOperatorSetForQuorums(
context.Background(),
[][]gethcommon.Address{{addr}},
quorumNumbers,
true,
)
require.NoError(t, err)
require.NotNil(t, receipt)
})

t.Run("deregister operator", func(t *testing.T) {
receipt, err := chainWriter.DeregisterOperator(
context.Background(),
quorumNumbers,
chainioutils.ConvertToBN254G1Point(keypair.PubKey),
true,
)
require.NoError(t, err)
require.NotNil(t, receipt)
})
}
13 changes: 13 additions & 0 deletions testutils/anvil.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log"
"log/slog"
"os/exec"
"path/filepath"
"runtime"
Expand Down Expand Up @@ -157,3 +158,15 @@ func AdvanceChainByNBlocksExecInContainer(ctx context.Context, n int, anvilC tes
log.Fatalf("Unable to advance anvil chain by n blocks. Expected return code 0, got %v", c)
}
}

type TestConfig struct {
AnvilStateFileName string
LogLevel slog.Level
}

func GetDefaultTestConfig() TestConfig {
return TestConfig{
AnvilStateFileName: "contracts-deployed-anvil-state.json",
LogLevel: slog.LevelDebug,
}
}