From 6b3002746b3766df6cec3db063f683a46b5e07a6 Mon Sep 17 00:00:00 2001 From: Connor Stein Date: Mon, 23 Sep 2024 16:07:41 -0400 Subject: [PATCH] Fix state view (#14532) --- integration-tests/deployment/address_book.go | 15 +++++++++----- .../deployment/address_book_test.go | 10 +++++++++- integration-tests/deployment/ccip/state.go | 20 ++++++++++++------- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/integration-tests/deployment/address_book.go b/integration-tests/deployment/address_book.go index 4a5916111c7..be004f27d0d 100644 --- a/integration-tests/deployment/address_book.go +++ b/integration-tests/deployment/address_book.go @@ -13,6 +13,7 @@ import ( var ( ErrInvalidChainSelector = fmt.Errorf("invalid chain selector") ErrInvalidAddress = fmt.Errorf("invalid address") + ErrChainNotFound = fmt.Errorf("chain not found") ) // ContractType is a simple string type for identifying contract types. @@ -90,7 +91,7 @@ type AddressBookMap struct { func (m *AddressBookMap) Save(chainSelector uint64, address string, typeAndVersion TypeAndVersion) error { _, exists := chainsel.ChainBySelector(chainSelector) if !exists { - return errors.Wrapf(ErrInvalidChainSelector, "chain selector %d not found", chainSelector) + return errors.Wrapf(ErrInvalidChainSelector, "chain selector %d", chainSelector) } if address == "" || address == common.HexToAddress("0x0").Hex() { return errors.Wrap(ErrInvalidAddress, "address cannot be empty") @@ -119,11 +120,15 @@ func (m *AddressBookMap) Addresses() (map[uint64]map[string]TypeAndVersion, erro return m.AddressesByChain, nil } -func (m *AddressBookMap) AddressesForChain(chain uint64) (map[string]TypeAndVersion, error) { - if _, exists := m.AddressesByChain[chain]; !exists { - return nil, fmt.Errorf("chain %d not found", chain) +func (m *AddressBookMap) AddressesForChain(chainSelector uint64) (map[string]TypeAndVersion, error) { + _, exists := chainsel.ChainBySelector(chainSelector) + if !exists { + return nil, errors.Wrapf(ErrInvalidChainSelector, "chain selector %d", chainSelector) + } + if _, exists := m.AddressesByChain[chainSelector]; !exists { + return nil, errors.Wrapf(ErrChainNotFound, "chain selector %d", chainSelector) } - return m.AddressesByChain[chain], nil + return m.AddressesByChain[chainSelector], nil } // Attention this will mutate existing book diff --git a/integration-tests/deployment/address_book_test.go b/integration-tests/deployment/address_book_test.go index c6967df0caf..bf3d2ad965c 100644 --- a/integration-tests/deployment/address_book_test.go +++ b/integration-tests/deployment/address_book_test.go @@ -20,16 +20,24 @@ func TestAddressBook_Save(t *testing.T) { err := ab.Save(chainsel.TEST_90000001.Selector, addr1, onRamp100) require.NoError(t, err) - // Check input validation + // Invalid address err = ab.Save(chainsel.TEST_90000001.Selector, "asdlfkj", onRamp100) require.Error(t, err) assert.Equal(t, errors.Is(err, ErrInvalidAddress), true, "err %s", err) + + // Valid chain but not present. + _, err = ab.AddressesForChain(chainsel.TEST_90000002.Selector) + assert.Equal(t, errors.Is(err, ErrChainNotFound), true, "err %s", err) + + // Invalid selector err = ab.Save(0, addr1, onRamp100) require.Error(t, err) assert.Equal(t, errors.Is(err, ErrInvalidChainSelector), true) + // Duplicate err = ab.Save(chainsel.TEST_90000001.Selector, addr1, onRamp100) require.Error(t, err) + // Zero address err = ab.Save(chainsel.TEST_90000001.Selector, common.HexToAddress("0x0").Hex(), onRamp100) require.Error(t, err) diff --git a/integration-tests/deployment/ccip/state.go b/integration-tests/deployment/ccip/state.go index efb3416ec3f..334c945707b 100644 --- a/integration-tests/deployment/ccip/state.go +++ b/integration-tests/deployment/ccip/state.go @@ -6,7 +6,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink/integration-tests/deployment" @@ -35,6 +34,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" ) +// CCIPChainState holds a Go binding for all the currently deployed CCIP contracts +// on a chain. If a binding is nil, it means here is no such contract on the chain. type CCIPChainState struct { OnRamp *onramp.OnRamp OffRamp *offramp.OffRamp @@ -177,12 +178,17 @@ func LoadOnchainState(e deployment.Environment, ab deployment.AddressBook) (CCIP state := CCIPOnChainState{ Chains: make(map[uint64]CCIPChainState), } - addresses, err := ab.Addresses() - if err != nil { - return state, errors.Wrap(err, "could not get addresses") - } - for chainSelector, addresses := range addresses { - chainState, err := LoadChainState(e.Chains[chainSelector], addresses) + for chainSelector, chain := range e.Chains { + addresses, err := ab.AddressesForChain(chainSelector) + if err != nil { + // Chain not found in address book, initialize empty + if errors.Is(err, deployment.ErrChainNotFound) { + addresses = make(map[string]deployment.TypeAndVersion) + } else { + return state, err + } + } + chainState, err := LoadChainState(chain, addresses) if err != nil { return state, err }