diff --git a/deployment/ccip/changeset/accept_ownership_test.go b/deployment/ccip/changeset/accept_ownership_test.go index 780af20f075..1c83d368a45 100644 --- a/deployment/ccip/changeset/accept_ownership_test.go +++ b/deployment/ccip/changeset/accept_ownership_test.go @@ -1,18 +1,16 @@ package changeset import ( - "math/big" "testing" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/deployment" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/stretchr/testify/require" "golang.org/x/exp/maps" @@ -21,7 +19,7 @@ import ( ) func Test_NewAcceptOwnershipChangeset(t *testing.T) { - e := NewMemoryEnvironmentWithJobs(t, logger.TestLogger(t), 2, 4) + e := NewMemoryEnvironmentWithJobsAndContracts(t, logger.TestLogger(t), 2, 4, &TestConfigs{}) state, err := LoadOnchainState(e.Env) require.NoError(t, err) @@ -29,40 +27,6 @@ func Test_NewAcceptOwnershipChangeset(t *testing.T) { source := allChains[0] dest := allChains[1] - newAddresses := deployment.NewMemoryAddressBook() - err = deployPrerequisiteChainContracts(e.Env, newAddresses, allChains, nil) - require.NoError(t, err) - require.NoError(t, e.Env.ExistingAddresses.Merge(newAddresses)) - - mcmConfig := commontypes.MCMSWithTimelockConfig{ - Canceller: commonchangeset.SingleGroupMCMS(t), - Bypasser: commonchangeset.SingleGroupMCMS(t), - Proposer: commonchangeset.SingleGroupMCMS(t), - TimelockExecutors: e.Env.AllDeployerKeys(), - TimelockMinDelay: big.NewInt(0), - } - out, err := commonchangeset.DeployMCMSWithTimelock(e.Env, map[uint64]commontypes.MCMSWithTimelockConfig{ - source: mcmConfig, - dest: mcmConfig, - }) - require.NoError(t, err) - require.NoError(t, e.Env.ExistingAddresses.Merge(out.AddressBook)) - newAddresses = deployment.NewMemoryAddressBook() - tokenConfig := NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) - ocrParams := make(map[uint64]CCIPOCRParams) - for _, chain := range allChains { - ocrParams[chain] = DefaultOCRParams(e.FeedChainSel, nil) - } - err = deployCCIPContracts(e.Env, newAddresses, NewChainsConfig{ - HomeChainSel: e.HomeChainSel, - FeedChainSel: e.FeedChainSel, - ChainsToDeploy: allChains, - TokenConfig: tokenConfig, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), - OCRParams: ocrParams, - }) - require.NoError(t, err) - // at this point we have the initial deploys done, now we need to transfer ownership // to the timelock contract state, err = LoadOnchainState(e.Env) diff --git a/deployment/ccip/changeset/active_candidate.go b/deployment/ccip/changeset/active_candidate.go index bc65cef71e7..e3391c9226c 100644 --- a/deployment/ccip/changeset/active_candidate.go +++ b/deployment/ccip/changeset/active_candidate.go @@ -74,6 +74,7 @@ func SetCandidatePluginChangeset( ccipOCRParams := DefaultOCRParams( feedChainSel, tokenConfig.GetTokenInfo(e.Logger, state.Chains[newChainSel].LinkToken, state.Chains[newChainSel].Weth9), + nil, ) newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( ocrSecrets, diff --git a/deployment/ccip/changeset/active_candidate_test.go b/deployment/ccip/changeset/active_candidate_test.go index 70280a33bb0..4d72ab6ccf2 100644 --- a/deployment/ccip/changeset/active_candidate_test.go +++ b/deployment/ccip/changeset/active_candidate_test.go @@ -141,6 +141,7 @@ func TestActiveCandidate(t *testing.T) { ccipOCRParams := DefaultOCRParams( tenv.FeedChainSel, tokenConfig.GetTokenInfo(e.Logger, state.Chains[tenv.FeedChainSel].LinkToken, state.Chains[tenv.FeedChainSel].Weth9), + nil, ) ocr3ConfigMap, err := internal.BuildOCR3ConfigForCCIPHome( deployment.XXXGenerateTestOCRSecrets(), diff --git a/deployment/ccip/changeset/add_chain.go b/deployment/ccip/changeset/add_chain.go index d97915c4022..958fdd4d095 100644 --- a/deployment/ccip/changeset/add_chain.go +++ b/deployment/ccip/changeset/add_chain.go @@ -5,6 +5,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" @@ -119,6 +120,8 @@ func AddDonAndSetCandidateChangeset( ccipOCRParams := DefaultOCRParams( feedChainSel, tokenConfig.GetTokenInfo(e.Logger, state.Chains[newChainSel].LinkToken, state.Chains[newChainSel].Weth9), + // TODO: Need USDC support. + nil, ) newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( ocrSecrets, diff --git a/deployment/ccip/changeset/add_chain_test.go b/deployment/ccip/changeset/add_chain_test.go index 39ae27f9444..96727d0e4f8 100644 --- a/deployment/ccip/changeset/add_chain_test.go +++ b/deployment/ccip/changeset/add_chain_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -61,12 +62,15 @@ func TestAddChainInbound(t *testing.T) { newAddresses = deployment.NewMemoryAddressBook() tokenConfig := NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) + chainConfig := make(map[uint64]CCIPOCRParams) + for _, chain := range initialDeploy { + chainConfig[chain] = DefaultOCRParams(e.FeedChainSel, nil, nil) + } err = deployCCIPContracts(e.Env, newAddresses, NewChainsConfig{ - HomeChainSel: e.HomeChainSel, - FeedChainSel: e.FeedChainSel, - ChainsToDeploy: initialDeploy, - TokenConfig: tokenConfig, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + HomeChainSel: e.HomeChainSel, + FeedChainSel: e.FeedChainSel, + ChainConfigByChain: chainConfig, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), }) require.NoError(t, err) diff --git a/deployment/ccip/changeset/deploy.go b/deployment/ccip/changeset/deploy.go index 68db44196ca..25271c59275 100644 --- a/deployment/ccip/changeset/deploy.go +++ b/deployment/ccip/changeset/deploy.go @@ -9,8 +9,6 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "golang.org/x/sync/errgroup" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/deployment" @@ -372,16 +370,12 @@ func configureChain( return fmt.Errorf("rmn home not found") } - for _, chainSel := range c.ChainsToDeploy { + for chainSel, chainConfig := range c.ChainConfigByChain { chain, _ := e.Chains[chainSel] chainState, ok := existingState.Chains[chain.Selector] if !ok { return fmt.Errorf("chain state not found for chain %d", chain.Selector) } - ocrParams, ok := c.OCRParams[chain.Selector] - if !ok { - return fmt.Errorf("OCR params not found for chain %d", chain.Selector) - } if chainState.OffRamp == nil { return fmt.Errorf("off ramp not found for chain %d", chain.Selector) } @@ -394,10 +388,6 @@ func configureChain( if err != nil { return err } - if enabled, ok := c.USDCConfig.EnabledChainMap()[chainSel]; ok && enabled { - ocrParams.ExecuteOffChainConfig.TokenDataObservers = c.USDCConfig.ToTokenDataObserverConfig() - } - ocrParams.CommitOffChainConfig.PriceFeedChainSelector = cciptypes.ChainSelector(c.FeedChainSel) // For each chain, we create a DON on the home chain (2 OCR instances) if err := addDON( e.Logger, @@ -409,7 +399,7 @@ func configureChain( chain, e.Chains[c.HomeChainSel], nodes.NonBootstraps(), - ocrParams, + chainConfig, ); err != nil { e.Logger.Errorw("Failed to add DON", "err", err) return err @@ -432,7 +422,7 @@ func deployCCIPContracts( e deployment.Environment, ab deployment.AddressBook, c NewChainsConfig) error { - err := deployChainContractsForChains(e, ab, c.HomeChainSel, c.ChainsToDeploy) + err := deployChainContractsForChains(e, ab, c.HomeChainSel, c.Chains()) if err != nil { e.Logger.Errorw("Failed to deploy chain contracts", "err", err) return err @@ -442,18 +432,6 @@ func deployCCIPContracts( e.Logger.Errorw("Failed to merge address book", "err", err) return err } - state, err := LoadOnchainState(e) - if err != nil { - e.Logger.Errorw("Failed to load existing onchain state", "err", err) - return err - } - - ocrParams := make(map[uint64]CCIPOCRParams) - for _, chain := range c.ChainsToDeploy { - tokenInfo := c.TokenConfig.GetTokenInfo(e.Logger, state.Chains[chain].LinkToken, state.Chains[chain].Weth9) - ocrParams[chain] = DefaultOCRParams(c.FeedChainSel, tokenInfo) - } - c.OCRParams = ocrParams err = configureChain(e, c) if err != nil { e.Logger.Errorw("Failed to add chain", "err", err) diff --git a/deployment/ccip/changeset/deploy_home_chain.go b/deployment/ccip/changeset/deploy_home_chain.go index 881f7c386c3..73fd0c8b98c 100644 --- a/deployment/ccip/changeset/deploy_home_chain.go +++ b/deployment/ccip/changeset/deploy_home_chain.go @@ -288,7 +288,7 @@ func AddChainConfig( chainSelector uint64, p2pIDs [][32]byte, ) (ccip_home.CCIPHomeChainConfigArgs, error) { - // First Add ChainConfig that includes all p2pIDs as readers + // First Add CCIPOCRParams that includes all p2pIDs as readers encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000), DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0), diff --git a/deployment/ccip/changeset/initial_add_chain.go b/deployment/ccip/changeset/initial_add_chain.go index 841f2014204..d4aaa3ee859 100644 --- a/deployment/ccip/changeset/initial_add_chain.go +++ b/deployment/ccip/changeset/initial_add_chain.go @@ -3,16 +3,14 @@ package changeset import ( "fmt" "os" - "slices" - "sort" "time" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-ccip/pluginconfig" "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -20,8 +18,8 @@ import ( var _ deployment.ChangeSet[NewChainsConfig] = ConfigureNewChains -// ConfigureNewChains enables new chains as destination for CCIP -// It performs the following steps: +// ConfigureNewChains enables new chains as destination(s) for CCIP +// It performs the following steps per chain: // - AddChainConfig + AddDON (candidate->primary promotion i.e. init) on the home chain // - SetOCR3Config on the remote chain // ConfigureNewChains assumes that the home chain is already enabled and all CCIP contracts are already deployed. @@ -41,67 +39,42 @@ func ConfigureNewChains(env deployment.Environment, c NewChainsConfig) (deployme }, nil } -type USDCConfig struct { - EnabledChains []uint64 - USDCAttestationConfig - CCTPTokenConfig map[ccipocr3.ChainSelector]pluginconfig.USDCCCTPTokenConfig -} - -func (cfg USDCConfig) EnabledChainMap() map[uint64]bool { - m := make(map[uint64]bool) - for _, chain := range cfg.EnabledChains { - m[chain] = true - } - return m -} - -func (cfg USDCConfig) ToTokenDataObserverConfig() []pluginconfig.TokenDataObserverConfig { - return []pluginconfig.TokenDataObserverConfig{{ - Type: pluginconfig.USDCCCTPHandlerType, - Version: "1.0", - USDCCCTPObserverConfig: &pluginconfig.USDCCCTPObserverConfig{ - Tokens: cfg.CCTPTokenConfig, - AttestationAPI: cfg.API, - AttestationAPITimeout: cfg.APITimeout, - AttestationAPIInterval: cfg.APIInterval, - }, - }} -} - -type USDCAttestationConfig struct { - API string - APITimeout *config.Duration - APIInterval *config.Duration -} - type CCIPOCRParams struct { - OCRParameters types.OCRParameters - CommitOffChainConfig pluginconfig.CommitOffchainConfig + OCRParameters types.OCRParameters + // Note contains pointers to Arb feeds for prices + CommitOffChainConfig pluginconfig.CommitOffchainConfig + // Note ontains USDC config ExecuteOffChainConfig pluginconfig.ExecuteOffchainConfig } -func (p CCIPOCRParams) Validate() error { - if err := p.OCRParameters.Validate(); err != nil { +func (c CCIPOCRParams) Validate() error { + if err := c.OCRParameters.Validate(); err != nil { return fmt.Errorf("invalid OCR parameters: %w", err) } - if err := p.CommitOffChainConfig.Validate(); err != nil { + if err := c.CommitOffChainConfig.Validate(); err != nil { return fmt.Errorf("invalid commit off-chain config: %w", err) } - if err := p.ExecuteOffChainConfig.Validate(); err != nil { + if err := c.ExecuteOffChainConfig.Validate(); err != nil { return fmt.Errorf("invalid execute off-chain config: %w", err) } return nil } type NewChainsConfig struct { - HomeChainSel uint64 - FeedChainSel uint64 - ChainsToDeploy []uint64 - TokenConfig TokenConfig - USDCConfig USDCConfig - // For setting OCR configuration - OCRSecrets deployment.OCRSecrets - OCRParams map[uint64]CCIPOCRParams + // Common to all chains + HomeChainSel uint64 + FeedChainSel uint64 + OCRSecrets deployment.OCRSecrets + // Per chain config + ChainConfigByChain map[uint64]CCIPOCRParams +} + +func (c NewChainsConfig) Chains() []uint64 { + chains := make([]uint64, 0, len(c.ChainConfigByChain)) + for chain := range c.ChainConfigByChain { + chains = append(chains, chain) + } + return chains } func (c NewChainsConfig) Validate() error { @@ -111,63 +84,27 @@ func (c NewChainsConfig) Validate() error { if err := deployment.IsValidChainSelector(c.FeedChainSel); err != nil { return fmt.Errorf("invalid feed chain selector: %d - %w", c.FeedChainSel, err) } - mapChainsToDeploy := make(map[uint64]bool) - for _, cs := range c.ChainsToDeploy { - mapChainsToDeploy[cs] = true - if err := deployment.IsValidChainSelector(cs); err != nil { - return fmt.Errorf("invalid chain selector: %d - %w", cs, err) - } - } - for token := range c.TokenConfig.TokenSymbolToInfo { - if err := c.TokenConfig.TokenSymbolToInfo[token].Validate(); err != nil { - return fmt.Errorf("invalid token config for token %s: %w", token, err) - } - } if c.OCRSecrets.IsEmpty() { return fmt.Errorf("no OCR secrets provided") } - usdcEnabledChainMap := c.USDCConfig.EnabledChainMap() - for chain := range usdcEnabledChainMap { - if _, exists := mapChainsToDeploy[chain]; !exists { - return fmt.Errorf("chain %d is not in chains to deploy", chain) - } - if err := deployment.IsValidChainSelector(chain); err != nil { - return fmt.Errorf("invalid chain selector: %d - %w", chain, err) - } - } - for chain := range c.USDCConfig.CCTPTokenConfig { - if _, exists := mapChainsToDeploy[uint64(chain)]; !exists { - return fmt.Errorf("chain %d is not in chains to deploy", chain) - } - if _, exists := usdcEnabledChainMap[uint64(chain)]; !exists { - return fmt.Errorf("chain %d is not enabled in USDC config", chain) - } - if err := deployment.IsValidChainSelector(uint64(chain)); err != nil { - return fmt.Errorf("invalid chain selector: %d - %w", chain, err) - } - } - // Validate OCR params - var ocrChains []uint64 - for chain, ocrParams := range c.OCRParams { - ocrChains = append(ocrChains, chain) - if _, exists := mapChainsToDeploy[chain]; !exists { - return fmt.Errorf("chain %d is not in chains to deploy", chain) - } - if err := ocrParams.Validate(); err != nil { + // Validate chain config + for chain, cfg := range c.ChainConfigByChain { + if err := cfg.Validate(); err != nil { return fmt.Errorf("invalid OCR params for chain %d: %w", chain, err) } - } - sort.Slice(ocrChains, func(i, j int) bool { return ocrChains[i] < ocrChains[j] }) - sort.Slice(c.ChainsToDeploy, func(i, j int) bool { return c.ChainsToDeploy[i] < c.ChainsToDeploy[j] }) - if !slices.Equal(ocrChains, c.ChainsToDeploy) { - return fmt.Errorf("mismatch in given OCR params and chains to deploy") + if cfg.CommitOffChainConfig.PriceFeedChainSelector != ccipocr3.ChainSelector(c.FeedChainSel) { + return fmt.Errorf("chain %d has invalid feed chain selector", chain) + } } return nil } +// DefaultOCRParams returns the default OCR parameters for a chain, +// except for a few values which must be parameterized (passed as arguments). func DefaultOCRParams( feedChainSel uint64, tokenInfo map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo, + tokenDataObservers []pluginconfig.TokenDataObserverConfig, ) CCIPOCRParams { return CCIPOCRParams{ OCRParameters: types.OCRParameters{ @@ -191,6 +128,7 @@ func DefaultOCRParams( RootSnoozeTime: *config.MustNewDuration(internal.RootSnoozeTime), MessageVisibilityInterval: *config.MustNewDuration(internal.FirstBlockAge), BatchingStrategyID: internal.BatchingStrategyID, + TokenDataObservers: tokenDataObservers, }, CommitOffChainConfig: pluginconfig.CommitOffchainConfig{ RemoteGasPriceBatchWriteFrequency: *config.MustNewDuration(internal.RemoteGasPriceBatchWriteFrequency), diff --git a/deployment/ccip/changeset/test_helpers.go b/deployment/ccip/changeset/test_helpers.go index a63a81b21c7..22ec324609c 100644 --- a/deployment/ccip/changeset/test_helpers.go +++ b/deployment/ccip/changeset/test_helpers.go @@ -268,16 +268,15 @@ func NewMemoryEnvironmentWithJobsAndContracts(t *testing.T, lggr logger.Logger, var err error e := NewMemoryEnvironment(t, lggr, numChains, numNodes, MockLinkPrice, MockWethPrice) allChains := e.Env.AllChainSelectors() - cfg := commontypes.MCMSWithTimelockConfig{ - Canceller: commonchangeset.SingleGroupMCMS(t), - Bypasser: commonchangeset.SingleGroupMCMS(t), - Proposer: commonchangeset.SingleGroupMCMS(t), - TimelockExecutors: e.Env.AllDeployerKeys(), - TimelockMinDelay: big.NewInt(0), - } mcmsCfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) for _, c := range e.Env.AllChainSelectors() { - mcmsCfg[c] = cfg + mcmsCfg[c] = commontypes.MCMSWithTimelockConfig{ + Canceller: commonchangeset.SingleGroupMCMS(t), + Bypasser: commonchangeset.SingleGroupMCMS(t), + Proposer: commonchangeset.SingleGroupMCMS(t), + TimelockExecutors: e.Env.AllDeployerKeys(), + TimelockMinDelay: big.NewInt(0), + } } var usdcChains []uint64 if tCfg != nil && tCfg.IsUSDC { @@ -311,56 +310,58 @@ func NewMemoryEnvironmentWithJobsAndContracts(t *testing.T, lggr logger.Logger, state, err := LoadOnchainState(e.Env) require.NoError(t, err) - tokenConfig := NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) - ocrParams := make(map[uint64]CCIPOCRParams) - usdcCCTPConfig := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig) - timelocksPerChain := make(map[uint64]*gethwrappers.RBACTimelock) + // Assert USDC set up as expected. for _, chain := range usdcChains { require.NotNil(t, state.Chains[chain].MockUSDCTokenMessenger) require.NotNil(t, state.Chains[chain].MockUSDCTransmitter) require.NotNil(t, state.Chains[chain].USDCTokenPool) - usdcCCTPConfig[cciptypes.ChainSelector(chain)] = pluginconfig.USDCCCTPTokenConfig{ - SourcePoolAddress: state.Chains[chain].USDCTokenPool.Address().String(), - SourceMessageTransmitterAddr: state.Chains[chain].MockUSDCTransmitter.Address().String(), - } } + // Assert link present require.NotNil(t, state.Chains[e.FeedChainSel].LinkToken) require.NotNil(t, state.Chains[e.FeedChainSel].Weth9) - var usdcCfg USDCAttestationConfig + + tokenConfig := NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) + var tokenDataProviders []pluginconfig.TokenDataObserverConfig if len(usdcChains) > 0 { server := mockAttestationResponse() endpoint := server.URL - usdcCfg = USDCAttestationConfig{ - API: endpoint, - APITimeout: commonconfig.MustNewDuration(time.Second), - APIInterval: commonconfig.MustNewDuration(500 * time.Millisecond), - } t.Cleanup(func() { server.Close() }) - } - + cctpContracts := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig) + for _, usdcChain := range usdcChains { + cctpContracts[cciptypes.ChainSelector(usdcChain)] = pluginconfig.USDCCCTPTokenConfig{ + SourcePoolAddress: state.Chains[usdcChain].USDCTokenPool.Address().String(), + SourceMessageTransmitterAddr: state.Chains[usdcChain].MockUSDCTransmitter.Address().String(), + } + } + tokenDataProviders = append(tokenDataProviders, pluginconfig.TokenDataObserverConfig{ + Type: pluginconfig.USDCCCTPHandlerType, + Version: "1.0", + USDCCCTPObserverConfig: &pluginconfig.USDCCCTPObserverConfig{ + Tokens: cctpContracts, + AttestationAPI: endpoint, + AttestationAPITimeout: commonconfig.MustNewDuration(time.Second), + AttestationAPIInterval: commonconfig.MustNewDuration(500 * time.Millisecond), + }}) + } + // Build the per chain config. + chainConfigs := make(map[uint64]CCIPOCRParams) + timelocksPerChain := make(map[uint64]*gethwrappers.RBACTimelock) for _, chain := range allChains { timelocksPerChain[chain] = state.Chains[chain].Timelock tokenInfo := tokenConfig.GetTokenInfo(e.Env.Logger, state.Chains[chain].LinkToken, state.Chains[chain].Weth9) - ocrParams[chain] = DefaultOCRParams(e.FeedChainSel, tokenInfo) + chainConfigs[chain] = DefaultOCRParams(e.FeedChainSel, tokenInfo, tokenDataProviders) } // Deploy second set of changesets to deploy and configure the CCIP contracts. e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ { Changeset: commonchangeset.WrapChangeSet(ConfigureNewChains), Config: NewChainsConfig{ - HomeChainSel: e.HomeChainSel, - FeedChainSel: e.FeedChainSel, - ChainsToDeploy: allChains, - TokenConfig: tokenConfig, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), - USDCConfig: USDCConfig{ - EnabledChains: usdcChains, - USDCAttestationConfig: usdcCfg, - CCTPTokenConfig: usdcCCTPConfig, - }, - OCRParams: ocrParams, + HomeChainSel: e.HomeChainSel, + FeedChainSel: e.FeedChainSel, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + ChainConfigByChain: chainConfigs, }, }, { diff --git a/integration-tests/testsetups/ccip/test_helpers.go b/integration-tests/testsetups/ccip/test_helpers.go index a2c680ee814..8ffce77cc6b 100644 --- a/integration-tests/testsetups/ccip/test_helpers.go +++ b/integration-tests/testsetups/ccip/test_helpers.go @@ -140,16 +140,15 @@ func NewLocalDevEnvironment( if tCfg.IsUSDC { usdcChains = allChains } - mcmsCfgPerChain := commontypes.MCMSWithTimelockConfig{ - Canceller: commonchangeset.SingleGroupMCMS(t), - Bypasser: commonchangeset.SingleGroupMCMS(t), - Proposer: commonchangeset.SingleGroupMCMS(t), - TimelockExecutors: env.AllDeployerKeys(), - TimelockMinDelay: big.NewInt(0), - } mcmsCfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) for _, c := range env.AllChainSelectors() { - mcmsCfg[c] = mcmsCfgPerChain + mcmsCfg[c] = commontypes.MCMSWithTimelockConfig{ + Canceller: commonchangeset.SingleGroupMCMS(t), + Bypasser: commonchangeset.SingleGroupMCMS(t), + Proposer: commonchangeset.SingleGroupMCMS(t), + TimelockExecutors: env.AllDeployerKeys(), + TimelockMinDelay: big.NewInt(0), + } } // Need to deploy prerequisites first so that we can form the USDC config // no proposals to be made, timelock can be passed as nil here @@ -189,64 +188,56 @@ func NewLocalDevEnvironment( }, }) require.NoError(t, err) - state, err := changeset.LoadOnchainState(env) require.NoError(t, err) - tokenConfig := changeset.NewTestTokenConfig(state.Chains[feedSel].USDFeeds) - usdcCCTPConfig := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig) - timelocksPerChain := make(map[uint64]*gethwrappers.RBACTimelock) - ocrParams := make(map[uint64]changeset.CCIPOCRParams) - for _, chain := range usdcChains { - require.NotNil(t, state.Chains[chain].MockUSDCTokenMessenger) - require.NotNil(t, state.Chains[chain].MockUSDCTransmitter) - require.NotNil(t, state.Chains[chain].USDCTokenPool) - usdcCCTPConfig[cciptypes.ChainSelector(chain)] = pluginconfig.USDCCCTPTokenConfig{ - SourcePoolAddress: state.Chains[chain].USDCTokenPool.Address().String(), - SourceMessageTransmitterAddr: state.Chains[chain].MockUSDCTransmitter.Address().String(), - } - } - var usdcAttestationCfg changeset.USDCAttestationConfig + + var tokenDataProviders []pluginconfig.TokenDataObserverConfig if len(usdcChains) > 0 { var endpoint string err = ccipactions.SetMockServerWithUSDCAttestation(testEnv.MockAdapter, nil) require.NoError(t, err) endpoint = testEnv.MockAdapter.InternalEndpoint - usdcAttestationCfg = changeset.USDCAttestationConfig{ - API: endpoint, - APITimeout: commonconfig.MustNewDuration(time.Second), - APIInterval: commonconfig.MustNewDuration(500 * time.Millisecond), + cctpContracts := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig) + for _, usdcChain := range usdcChains { + cctpContracts[cciptypes.ChainSelector(usdcChain)] = pluginconfig.USDCCCTPTokenConfig{ + SourcePoolAddress: state.Chains[usdcChain].USDCTokenPool.Address().String(), + SourceMessageTransmitterAddr: state.Chains[usdcChain].MockUSDCTransmitter.Address().String(), + } } - } - require.NotNil(t, state.Chains[feedSel].LinkToken) - require.NotNil(t, state.Chains[feedSel].Weth9) - + tokenDataProviders = append(tokenDataProviders, pluginconfig.TokenDataObserverConfig{ + Type: pluginconfig.USDCCCTPHandlerType, + Version: "1.0", + USDCCCTPObserverConfig: &pluginconfig.USDCCCTPObserverConfig{ + Tokens: cctpContracts, + AttestationAPI: endpoint, + AttestationAPITimeout: commonconfig.MustNewDuration(time.Second), + AttestationAPIInterval: commonconfig.MustNewDuration(500 * time.Millisecond), + }}) + } + + // Build the per chain config. + tokenConfig := changeset.NewTestTokenConfig(state.Chains[feedSel].USDFeeds) + chainConfigs := make(map[uint64]changeset.CCIPOCRParams) + timelocksPerChain := make(map[uint64]*gethwrappers.RBACTimelock) for _, chain := range allChains { timelocksPerChain[chain] = state.Chains[chain].Timelock - tokenInfo := tokenConfig.GetTokenInfo(env.Logger, state.Chains[chain].LinkToken, state.Chains[chain].Weth9) - - params := changeset.DefaultOCRParams(feedSel, tokenInfo) + tokenInfo := tokenConfig.GetTokenInfo(e.Logger, state.Chains[chain].LinkToken, state.Chains[chain].Weth9) + ocrParams := changeset.DefaultOCRParams(feedSel, tokenInfo, tokenDataProviders) if tCfg.OCRConfigOverride != nil { - params = tCfg.OCRConfigOverride(params) + ocrParams = tCfg.OCRConfigOverride(ocrParams) } - - ocrParams[chain] = params + chainConfigs[chain] = ocrParams } + // Deploy second set of changesets to deploy and configure the CCIP contracts. env, err = commonchangeset.ApplyChangesets(t, env, timelocksPerChain, []commonchangeset.ChangesetApplication{ { Changeset: commonchangeset.WrapChangeSet(changeset.ConfigureNewChains), Config: changeset.NewChainsConfig{ - HomeChainSel: homeChainSel, - FeedChainSel: feedSel, - ChainsToDeploy: allChains, - TokenConfig: tokenConfig, - OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), - OCRParams: ocrParams, - USDCConfig: changeset.USDCConfig{ - EnabledChains: usdcChains, - USDCAttestationConfig: usdcAttestationCfg, - CCTPTokenConfig: usdcCCTPConfig, - }, + HomeChainSel: homeChainSel, + FeedChainSel: feedSel, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + ChainConfigByChain: chainConfigs, }, }, { @@ -656,7 +647,7 @@ func FundNodes(t *testing.T, lggr zerolog.Logger, env *test_env.CLClusterTestEnv require.NoError(t, fundGrp.Wait(), "Error funding chainlink nodes") } -// CreateChainConfigFromNetworks creates a list of ChainConfig from the network config provided in test config. +// CreateChainConfigFromNetworks creates a list of CCIPOCRParams from the network config provided in test config. // It either creates it from the private ethereum networks created by the test environment or from the // network URLs provided in the network config ( if the network is a live testnet). // It uses the private keys from the network config to create the deployer key for each chain.