From cc616ee1fe64a48e80ac8baa06421c000044404a Mon Sep 17 00:00:00 2001 From: simsonraj Date: Fri, 22 May 2026 21:37:30 +0530 Subject: [PATCH] Parallelize Translate FQ changeset & some state loading to speed up run time --- .../operation/evm/v1_5/ops_evm2evm_onramp.go | 82 ++ .../evm/migration/seq_translate_onramp_fq.go | 72 +- deployment/ccip/shared/stateview/state.go | 720 +++++++++++------- 3 files changed, 553 insertions(+), 321 deletions(-) diff --git a/deployment/ccip/operation/evm/v1_5/ops_evm2evm_onramp.go b/deployment/ccip/operation/evm/v1_5/ops_evm2evm_onramp.go index ac213d8cd7e..aef181591f4 100644 --- a/deployment/ccip/operation/evm/v1_5/ops_evm2evm_onramp.go +++ b/deployment/ccip/operation/evm/v1_5/ops_evm2evm_onramp.go @@ -2,9 +2,12 @@ package v1_5 import ( "fmt" + "sync" "github.com/Masterminds/semver/v3" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "golang.org/x/sync/errgroup" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_onramp" cldf_evm "github.com/smartcontractkit/chainlink-deployments-framework/chain/evm" @@ -28,6 +31,15 @@ type GetPoolBySourceTokenIn struct { DestChainSelector uint64 } +type BatchOnRampGetTokenCfgIn struct { + OnRamp common.Address + Tokens []common.Address + ChainSelector uint64 +} + +// onRampBatchConcurrency caps concurrent RPC calls to avoid overwhelming the node/provider. +const onRampBatchConcurrency = 10 + var ( EVM2EVMOnrampGetDynamicCfgOp = operations.NewOperation( "EVM2EVMOnrampGetDynamicCfgOp", @@ -95,4 +107,74 @@ var ( } return tokenTransferFeeCfg, nil }) + + // EVM2EVMOnrampGetAllTokenTransferFeeConfigsOp fetches GetTokenTransferFeeConfig for every + // token in the input list concurrently + EVM2EVMOnrampGetAllTokenTransferFeeConfigsOp = operations.NewOperation( + "EVM2EVMOnrampGetAllTokenTransferFeeConfigsOp", + semver.MustParse("1.0.0"), + "Batch-fetches TokenTransferFeeConfig for all given tokens from a 1.5.0 OnRamp", + func(b operations.Bundle, deps MigrateOnRampToFQDeps, input BatchOnRampGetTokenCfgIn) (map[common.Address]evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfig, error) { + onramp, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(input.OnRamp, deps.Chain.Client) + if err != nil { + return nil, fmt.Errorf("failed to create EVM2EVMOnRamp contract binding: chainSelector=%d, OnRamp Address=%s, error=%w", deps.Chain.ChainSelector(), input.OnRamp.Hex(), err) + } + + var mu sync.Mutex + results := make(map[common.Address]evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfig, len(input.Tokens)) + grp, grpCtx := errgroup.WithContext(b.GetContext()) + grp.SetLimit(onRampBatchConcurrency) + for _, token := range input.Tokens { + token := token + grp.Go(func() error { + cfg, err := onramp.GetTokenTransferFeeConfig(&bind.CallOpts{Context: grpCtx}, token) + if err != nil { + return fmt.Errorf("failed to get token transfer fee config for token %s on OnRamp %s: %w", token.Hex(), input.OnRamp.Hex(), err) + } + mu.Lock() + results[token] = cfg + mu.Unlock() + return nil + }) + } + if err := grp.Wait(); err != nil { + return nil, err + } + return results, nil + }) + + // EVM2EVMOnrampGetAllFeeTokenConfigsOp fetches GetFeeTokenConfig for every token in the input + // list concurrently + EVM2EVMOnrampGetAllFeeTokenConfigsOp = operations.NewOperation( + "EVM2EVMOnrampGetAllFeeTokenConfigsOp", + semver.MustParse("1.0.0"), + "Batch-fetches FeeTokenConfig for all given fee tokens from a 1.5.0 OnRamp", + func(b operations.Bundle, deps MigrateOnRampToFQDeps, input BatchOnRampGetTokenCfgIn) (map[common.Address]evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfig, error) { + onRamp, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(input.OnRamp, deps.Chain.Client) + if err != nil { + return nil, fmt.Errorf("failed to create EVM2EVMOnRamp contract binding: chainSelector=%d, OnRamp Address=%s, error=%w", deps.Chain.ChainSelector(), input.OnRamp.Hex(), err) + } + + var mu sync.Mutex + results := make(map[common.Address]evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfig, len(input.Tokens)) + grp, grpCtx := errgroup.WithContext(b.GetContext()) + grp.SetLimit(onRampBatchConcurrency) + for _, token := range input.Tokens { + token := token + grp.Go(func() error { + cfg, err := onRamp.GetFeeTokenConfig(&bind.CallOpts{Context: grpCtx}, token) + if err != nil { + return fmt.Errorf("failed to get fee token config for token %s on OnRamp %s: %w", token.Hex(), input.OnRamp.Hex(), err) + } + mu.Lock() + results[token] = cfg + mu.Unlock() + return nil + }) + } + if err := grp.Wait(); err != nil { + return nil, err + } + return results, nil + }) ) diff --git a/deployment/ccip/sequence/evm/migration/seq_translate_onramp_fq.go b/deployment/ccip/sequence/evm/migration/seq_translate_onramp_fq.go index 7a80151a296..04180399d91 100644 --- a/deployment/ccip/sequence/evm/migration/seq_translate_onramp_fq.go +++ b/deployment/ccip/sequence/evm/migration/seq_translate_onramp_fq.go @@ -83,6 +83,22 @@ var ( return OnRampToFeeQuoterDestChainConfigOutput{}, fmt.Errorf("failed to Execute GetAllFeeTokensOps: %w", err) } + // Batch-fetch all fee token configs concurrently + allFeeTokenCfgsOp, err := operations.ExecuteOperation( + b, migration_ops.EVM2EVMOnrampGetAllFeeTokenConfigsOp, + migration_ops.MigrateOnRampToFQDeps{ + Chain: srcChain, + }, + migration_ops.BatchOnRampGetTokenCfgIn{ + OnRamp: onRamp1_5, + Tokens: allFeeTokensOp.Output, + ChainSelector: chainSel, + }, + ) + if err != nil { + return OnRampToFeeQuoterDestChainConfigOutput{}, fmt.Errorf("failed to batch-fetch fee token configs on source chain %d: %w", chainSel, err) + } + // add supported fee token config to FeeQuoter // This is per token in 1.5.0 onRamp, but in FeeQuoter its per destination chain, @@ -92,31 +108,17 @@ var ( feeTokenPremiumMultipliers := make([]fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs, 0, len(allFeeTokensOp.Output)) for _, ft := range allFeeTokensOp.Output { - feetokenCfgReport, err := operations.ExecuteOperation( - b, migration_ops.EVM2EVMOnrampGetFeeTokenConfigOp, - migration_ops.MigrateOnRampToFQDeps{ - Chain: srcChain, - }, - migration_ops.OnRampGetTokenCfgIn{ - OnRamp: onRamp1_5, - Address: ft, - ChainSelector: chainSel, - }, - ) - if err != nil { - return OnRampToFeeQuoterDestChainConfigOutput{}, fmt.Errorf("failed to Execute GetOnRampGetFeeTokenConfigOps: %w", err) - } - - if !feetokenCfgReport.Output.Enabled { + feeTokenCfg := allFeeTokenCfgsOp.Output[ft] + if !feeTokenCfg.Enabled { continue // skip disabled fee tokens, same as TTFC loop below } // Translate the feeToken PremiumMultiplierCfg to 1.6 FeeQuoter config premiumMultiplierCfg := EVM2EVMOnRampMigratePremiumMultiplierCfg{} - premiumMultiplierCfg.TranslateOnrampToFeeQFeePremiumCfg(ft, feetokenCfgReport.Output) + premiumMultiplierCfg.TranslateOnrampToFeeQFeePremiumCfg(ft, feeTokenCfg) feeTokenPremiumMultipliers = append(feeTokenPremiumMultipliers, premiumMultiplierCfg.FeeQuoterPremiumMultiplierWeiPerEthArgs) if onRampFeeTokenCfgReport == (evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfig{}) { - onRampFeeTokenCfgReport = feetokenCfgReport.Output + onRampFeeTokenCfgReport = feeTokenCfg } } @@ -175,28 +177,30 @@ var ( if err != nil { return OnRampToFeeQuoterTokenTransferFeeCfgOutput{}, fmt.Errorf("failed to get all configured tokens from TokenAdminRegistry on source chain %d: %w", chainSel, err) } + // Batch-fetch all token transfer fee configs concurrently allTokens := getAllConfiguredTokensOps.Output + batchCfgsOp, err := operations.ExecuteOperation( + b, migration_ops.EVM2EVMOnrampGetAllTokenTransferFeeConfigsOp, + migration_ops.MigrateOnRampToFQDeps{ + Chain: srcChain, + }, + migration_ops.BatchOnRampGetTokenCfgIn{ + OnRamp: onRamp1_5, + Tokens: allTokens, + ChainSelector: chainSel, + }, + ) + if err != nil { + return OnRampToFeeQuoterTokenTransferFeeCfgOutput{}, fmt.Errorf("failed to batch-fetch token transfer fee configs on source chain %d: %w", chainSel, err) + } for _, token := range allTokens { - tokenTransferFeeCfgOp, err := operations.ExecuteOperation( - b, migration_ops.EVM2EVMOnrampGetTokenTransferFeeConfigOp, - migration_ops.MigrateOnRampToFQDeps{ - Chain: srcChain, - }, - migration_ops.OnRampGetTokenCfgIn{ - OnRamp: onRamp1_5, - Address: token, - ChainSelector: chainSel, - }, - ) - if err != nil { - return OnRampToFeeQuoterTokenTransferFeeCfgOutput{}, fmt.Errorf("failed to get suported chains for the toksn Pool on source chain %d: %w", chainSel, err) - } - if !tokenTransferFeeCfgOp.Output.IsEnabled { + tokenTransferFeeCfg := batchCfgsOp.Output[token] + if !tokenTransferFeeCfg.IsEnabled { continue // skip this token if the transfer fee config is not enabled } allTransferTokensAndCfgs = append(allTransferTokensAndCfgs, - migrateOnRamp.TranslateOnrampToFeequoterTokenTransferFeeConfig(token, tokenTransferFeeCfgOp.Output), + migrateOnRamp.TranslateOnrampToFeequoterTokenTransferFeeConfig(token, tokenTransferFeeCfg), ) } tokenTransferFeeConfigsPerDestChain = append(tokenTransferFeeConfigsPerDestChain, fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{ diff --git a/deployment/ccip/shared/stateview/state.go b/deployment/ccip/shared/stateview/state.go index d08cd09963f..d68638cdd07 100644 --- a/deployment/ccip/shared/stateview/state.go +++ b/deployment/ccip/shared/stateview/state.go @@ -1038,7 +1038,6 @@ func LoadOnchainState(e cldf.Environment, opts ...LoadOption) (CCIPOnChainState, if err != nil { return CCIPOnChainState{}, err } - suiChains, err := suistate.LoadOnchainStatesui(e) if err != nil { return CCIPOnChainState{}, err @@ -1077,7 +1076,10 @@ func LoadOnchainState(e cldf.Environment, opts ...LoadOption) (CCIPOnChainState, if err := grp.Wait(); err != nil { return state, err } - return state, state.Validate() + if err := state.Validate(); err != nil { + return state, err + } + return state, nil } // LoadChainState Loads all state for a chain into state @@ -1104,7 +1106,10 @@ func LoadChainState(ctx context.Context, chain cldf_evm.Chain, addresses map[str return state, err } state.StaticLinkTokenState = *staticLinkState + state.ABIByAddress = make(map[string]string) + var mu sync.Mutex + var work []func(context.Context) error for address, tvStr := range addresses { switch tvStr.String() { case cldf.NewTypeAndVersion(commontypes.RBACTimelock, deployment.Version1_0_0).String(): @@ -1325,141 +1330,225 @@ func LoadChainState(ctx context.Context, chain cldf_evm.Chain, addresses map[str state.Multicall3 = mc state.ABIByAddress[address] = multicall3.Multicall3ABI case cldf.NewTypeAndVersion(ccipshared.PriceFeed, deployment.Version1_0_0).String(): - feed, err := aggregator_v3_interface.NewAggregatorV3Interface(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if state.USDFeeds == nil { - state.USDFeeds = make(map[ccipshared.TokenSymbol]*aggregator_v3_interface.AggregatorV3Interface) - } - desc, err := feed.Description(&bind.CallOpts{}) - if err != nil { - return state, err - } - keys, ok := ccipshared.GetSymbolsFromDescription(desc) - if !ok { - return state, fmt.Errorf("unknown feed description %s", desc) - } - for _, key := range keys { - state.USDFeeds[key] = feed - } - state.ABIByAddress[address] = aggregator_v3_interface.AggregatorV3InterfaceABI + addr := address + work = append(work, func(ctx context.Context) error { + feed, err := aggregator_v3_interface.NewAggregatorV3Interface(common.HexToAddress(addr), chain.Client) + if err != nil { + return err + } + desc, err := feed.Description(&bind.CallOpts{}) + if err != nil { + return err + } + keys, ok := ccipshared.GetSymbolsFromDescription(desc) + if !ok { + return fmt.Errorf("unknown feed description %s", desc) + } + mu.Lock() + if state.USDFeeds == nil { + state.USDFeeds = make(map[ccipshared.TokenSymbol]*aggregator_v3_interface.AggregatorV3Interface) + } + for _, key := range keys { + state.USDFeeds[key] = feed + } + state.ABIByAddress[addr] = aggregator_v3_interface.AggregatorV3InterfaceABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.BurnMintTokenPool, deployment.Version1_5_1).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_mint_token_pool.NewBurnMintTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.BurnMintTokenPools = helpers.AddValueToNestedMap(state.BurnMintTokenPools, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = burn_mint_token_pool.BurnMintTokenPoolABI + addr := address + work = append(work, func(ctx context.Context) error { + ethAddress := common.HexToAddress(addr) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_mint_token_pool.NewBurnMintTokenPool, ethAddress, chain.Client) + if err != nil { + return fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + mu.Lock() + state.BurnMintTokenPools = helpers.AddValueToNestedMap(state.BurnMintTokenPools, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[addr] = burn_mint_token_pool.BurnMintTokenPoolABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.BurnMintTokenPool, deployment.Version1_5_0).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_mint_token_pool_and_proxy.NewBurnMintTokenPoolAndProxy, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.BurnMintTokenPoolsAndProxies = helpers.AddValueToNestedMap(state.BurnMintTokenPoolsAndProxies, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = burn_mint_token_pool.BurnMintTokenPoolABI + addr := address + work = append(work, func(ctx context.Context) error { + ethAddress := common.HexToAddress(addr) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_mint_token_pool_and_proxy.NewBurnMintTokenPoolAndProxy, ethAddress, chain.Client) + if err != nil { + return fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + mu.Lock() + state.BurnMintTokenPoolsAndProxies = helpers.AddValueToNestedMap(state.BurnMintTokenPoolsAndProxies, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[addr] = burn_mint_token_pool.BurnMintTokenPoolABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.BurnMintTokenPool, deployment.Version1_6_1).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_mint_token_pool_v1_6_1.NewBurnMintTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.BurnMintTokenPoolsV1_6_1 = helpers.AddValueToNestedMap(state.BurnMintTokenPoolsV1_6_1, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = burn_mint_token_pool_v1_6_1.BurnMintTokenPoolABI + addr := address + work = append(work, func(ctx context.Context) error { + ethAddress := common.HexToAddress(addr) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_mint_token_pool_v1_6_1.NewBurnMintTokenPool, ethAddress, chain.Client) + if err != nil { + return fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + mu.Lock() + state.BurnMintTokenPoolsV1_6_1 = helpers.AddValueToNestedMap(state.BurnMintTokenPoolsV1_6_1, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[addr] = burn_mint_token_pool_v1_6_1.BurnMintTokenPoolABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.BurnMintFastTransferTokenPool, deployment.Version1_6_1).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, fast_transfer_token_pool.NewBurnMintFastTransferTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.BurnMintFastTransferTokenPools = helpers.AddValueToNestedMap(state.BurnMintFastTransferTokenPools, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = fast_transfer_token_pool.BurnMintFastTransferTokenPoolABI + addr := address + work = append(work, func(ctx context.Context) error { + ethAddress := common.HexToAddress(addr) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, fast_transfer_token_pool.NewBurnMintFastTransferTokenPool, ethAddress, chain.Client) + if err != nil { + return fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + mu.Lock() + state.BurnMintFastTransferTokenPools = helpers.AddValueToNestedMap(state.BurnMintFastTransferTokenPools, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[addr] = fast_transfer_token_pool.BurnMintFastTransferTokenPoolABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.BurnMintFastTransferTokenPool, deployment.Version1_6_3Dev).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, fast_transfer_token_pool.NewBurnMintFastTransferTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.BurnMintFastTransferTokenPools = helpers.AddValueToNestedMap(state.BurnMintFastTransferTokenPools, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = fast_transfer_token_pool.BurnMintFastTransferTokenPoolABI + addr := address + work = append(work, func(ctx context.Context) error { + ethAddress := common.HexToAddress(addr) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, fast_transfer_token_pool.NewBurnMintFastTransferTokenPool, ethAddress, chain.Client) + if err != nil { + return fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + mu.Lock() + state.BurnMintFastTransferTokenPools = helpers.AddValueToNestedMap(state.BurnMintFastTransferTokenPools, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[addr] = fast_transfer_token_pool.BurnMintFastTransferTokenPoolABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.BurnMintWithExternalMinterFastTransferTokenPool, deployment.Version1_6_0).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_mint_with_external_minter_fast_transfer_token_pool.NewBurnMintWithExternalMinterFastTransferTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.BurnMintWithExternalMinterFastTransferTokenPools = helpers.AddValueToNestedMap(state.BurnMintWithExternalMinterFastTransferTokenPools, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = burn_mint_with_external_minter_fast_transfer_token_pool.BurnMintWithExternalMinterFastTransferTokenPoolABI + addr := address + work = append(work, func(ctx context.Context) error { + ethAddress := common.HexToAddress(addr) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_mint_with_external_minter_fast_transfer_token_pool.NewBurnMintWithExternalMinterFastTransferTokenPool, ethAddress, chain.Client) + if err != nil { + return fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + mu.Lock() + state.BurnMintWithExternalMinterFastTransferTokenPools = helpers.AddValueToNestedMap(state.BurnMintWithExternalMinterFastTransferTokenPools, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[addr] = burn_mint_with_external_minter_fast_transfer_token_pool.BurnMintWithExternalMinterFastTransferTokenPoolABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.HybridWithExternalMinterFastTransferTokenPool, deployment.Version1_6_0).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, hybrid_with_external_minter_fast_transfer_token_pool.NewHybridWithExternalMinterFastTransferTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.HybridWithExternalMinterFastTransferTokenPools = helpers.AddValueToNestedMap(state.HybridWithExternalMinterFastTransferTokenPools, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = hybrid_with_external_minter_fast_transfer_token_pool.HybridWithExternalMinterFastTransferTokenPoolABI + addr := address + work = append(work, func(ctx context.Context) error { + ethAddress := common.HexToAddress(addr) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, hybrid_with_external_minter_fast_transfer_token_pool.NewHybridWithExternalMinterFastTransferTokenPool, ethAddress, chain.Client) + if err != nil { + return fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + mu.Lock() + state.HybridWithExternalMinterFastTransferTokenPools = helpers.AddValueToNestedMap(state.HybridWithExternalMinterFastTransferTokenPools, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[addr] = hybrid_with_external_minter_fast_transfer_token_pool.HybridWithExternalMinterFastTransferTokenPoolABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.BurnWithFromMintTokenPool, deployment.Version1_5_1).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_with_from_mint_token_pool.NewBurnWithFromMintTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.BurnWithFromMintTokenPools = helpers.AddValueToNestedMap(state.BurnWithFromMintTokenPools, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = burn_with_from_mint_token_pool.BurnWithFromMintTokenPoolABI + addr := address + work = append(work, func(ctx context.Context) error { + ethAddress := common.HexToAddress(addr) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_with_from_mint_token_pool.NewBurnWithFromMintTokenPool, ethAddress, chain.Client) + if err != nil { + return fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + mu.Lock() + state.BurnWithFromMintTokenPools = helpers.AddValueToNestedMap(state.BurnWithFromMintTokenPools, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[addr] = burn_with_from_mint_token_pool.BurnWithFromMintTokenPoolABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.BurnFromMintTokenPool, deployment.Version1_5_1).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_from_mint_token_pool.NewBurnFromMintTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.BurnFromMintTokenPools = helpers.AddValueToNestedMap(state.BurnFromMintTokenPools, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = burn_from_mint_token_pool.BurnFromMintTokenPoolABI + addr := address + work = append(work, func(ctx context.Context) error { + ethAddress := common.HexToAddress(addr) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_from_mint_token_pool.NewBurnFromMintTokenPool, ethAddress, chain.Client) + if err != nil { + return fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + mu.Lock() + state.BurnFromMintTokenPools = helpers.AddValueToNestedMap(state.BurnFromMintTokenPools, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[addr] = burn_from_mint_token_pool.BurnFromMintTokenPoolABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.LockReleaseTokenPool, deployment.Version1_5_1).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, lock_release_token_pool.NewLockReleaseTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.LockReleaseTokenPools = helpers.AddValueToNestedMap(state.LockReleaseTokenPools, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = lock_release_token_pool.LockReleaseTokenPoolABI + addr := address + work = append(work, func(ctx context.Context) error { + ethAddress := common.HexToAddress(addr) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, lock_release_token_pool.NewLockReleaseTokenPool, ethAddress, chain.Client) + if err != nil { + return fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + mu.Lock() + state.LockReleaseTokenPools = helpers.AddValueToNestedMap(state.LockReleaseTokenPools, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[addr] = lock_release_token_pool.LockReleaseTokenPoolABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.LockReleaseTokenPool, deployment.Version1_6_1).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, lock_release_token_pool_v1_6_1.NewLockReleaseTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.LockReleaseTokenPoolsV1_6_1 = helpers.AddValueToNestedMap(state.LockReleaseTokenPoolsV1_6_1, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = lock_release_token_pool_v1_6_1.LockReleaseTokenPoolABI + addr := address + work = append(work, func(ctx context.Context) error { + ethAddress := common.HexToAddress(addr) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, lock_release_token_pool_v1_6_1.NewLockReleaseTokenPool, ethAddress, chain.Client) + if err != nil { + return fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + mu.Lock() + state.LockReleaseTokenPoolsV1_6_1 = helpers.AddValueToNestedMap(state.LockReleaseTokenPoolsV1_6_1, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[addr] = lock_release_token_pool_v1_6_1.LockReleaseTokenPoolABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.BurnMintToken, deployment.Version1_0_0).String(): - tok, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if state.BurnMintTokens677 == nil { - state.BurnMintTokens677 = make(map[ccipshared.TokenSymbol]*burn_mint_erc677.BurnMintERC677) - } - symbol, err := tok.Symbol(nil) - if err != nil { - return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) - } - state.BurnMintTokens677[ccipshared.TokenSymbol(symbol)] = tok - state.ABIByAddress[address] = burn_mint_erc677.BurnMintERC677ABI + addr := address + work = append(work, func(ctx context.Context) error { + tok, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(addr), chain.Client) + if err != nil { + return err + } + symbol, err := tok.Symbol(nil) + if err != nil { + return fmt.Errorf("failed to get token symbol of token at %s: %w", addr, err) + } + mu.Lock() + if state.BurnMintTokens677 == nil { + state.BurnMintTokens677 = make(map[ccipshared.TokenSymbol]*burn_mint_erc677.BurnMintERC677) + } + state.BurnMintTokens677[ccipshared.TokenSymbol(symbol)] = tok + state.ABIByAddress[addr] = burn_mint_erc677.BurnMintERC677ABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.ERC20Token, deployment.Version1_0_0).String(): - tok, err := erc20.NewERC20(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if state.ERC20Tokens == nil { - state.ERC20Tokens = make(map[ccipshared.TokenSymbol]*erc20.ERC20) - } - symbol, err := tok.Symbol(nil) - if err != nil { - return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) - } - state.ERC20Tokens[ccipshared.TokenSymbol(symbol)] = tok - state.ABIByAddress[address] = erc20.ERC20ABI + addr := address + work = append(work, func(ctx context.Context) error { + tok, err := erc20.NewERC20(common.HexToAddress(addr), chain.Client) + if err != nil { + return err + } + symbol, err := tok.Symbol(nil) + if err != nil { + return fmt.Errorf("failed to get token symbol of token at %s: %w", addr, err) + } + mu.Lock() + if state.ERC20Tokens == nil { + state.ERC20Tokens = make(map[ccipshared.TokenSymbol]*erc20.ERC20) + } + state.ERC20Tokens[ccipshared.TokenSymbol(symbol)] = tok + state.ABIByAddress[addr] = erc20.ERC20ABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.FactoryBurnMintERC20Token, deployment.Version1_6_2).String(): tok, err := factoryBurnMintERC20v1_6_2.NewFactoryBurnMintERC20(common.HexToAddress(address), chain.Client) if err != nil { @@ -1475,19 +1564,25 @@ func LoadChainState(ctx context.Context, chain cldf_evm.Chain, addresses map[str state.FactoryBurnMintERC20Token1_5_1 = tok state.ABIByAddress[address] = factoryBurnMintERC20v1_5_1.FactoryBurnMintERC20ABI case cldf.NewTypeAndVersion(ccipshared.BurnMintERC20Token, deployment.Version1_0_0).String(): - tok, err := burn_mint_erc20.NewBurnMintERC20(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if state.BurnMintERC20 == nil { - state.BurnMintERC20 = make(map[ccipshared.TokenSymbol]*burn_mint_erc20.BurnMintERC20) - } - symbol, err := tok.Symbol(nil) - if err != nil { - return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) - } - state.BurnMintERC20[ccipshared.TokenSymbol(symbol)] = tok - state.ABIByAddress[address] = burn_mint_erc20.BurnMintERC20ABI + addr := address + work = append(work, func(ctx context.Context) error { + tok, err := burn_mint_erc20.NewBurnMintERC20(common.HexToAddress(addr), chain.Client) + if err != nil { + return err + } + symbol, err := tok.Symbol(nil) + if err != nil { + return fmt.Errorf("failed to get token symbol of token at %s: %w", addr, err) + } + mu.Lock() + if state.BurnMintERC20 == nil { + state.BurnMintERC20 = make(map[ccipshared.TokenSymbol]*burn_mint_erc20.BurnMintERC20) + } + state.BurnMintERC20[ccipshared.TokenSymbol(symbol)] = tok + state.ABIByAddress[addr] = burn_mint_erc20.BurnMintERC20ABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.ERC677Token, deployment.Version1_0_0).String(): tok, err := erc677.NewERC677(common.HexToAddress(address), chain.Client) if err != nil { @@ -1505,57 +1600,75 @@ func LoadChainState(ctx context.Context, chain cldf_evm.Chain, addresses map[str // legacy addresses below are commented out to avoid loading them by default, to be uncommented for migrations case cldf.NewTypeAndVersion(ccipshared.OnRamp, deployment.Version1_5_0).String(), cldf.NewTypeAndVersion(ccipshared.EVM2EVMOnRamp, deployment.Version1_5_0).String(): - if !config.loadLegacyContracts { - continue - } - onRampC, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - sCfg, err := onRampC.GetStaticConfig(nil) - if err != nil { - return state, fmt.Errorf("failed to get static config chain %s: %w", chain.String(), err) - } - if state.EVM2EVMOnRamp == nil { - state.EVM2EVMOnRamp = make(map[uint64]*evm_2_evm_onramp.EVM2EVMOnRamp) - } - state.EVM2EVMOnRamp[sCfg.DestChainSelector] = onRampC - state.ABIByAddress[address] = evm_2_evm_onramp.EVM2EVMOnRampABI + addr := address + work = append(work, func(ctx context.Context) error { + if !config.loadLegacyContracts { + return nil + } + onRampC, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(common.HexToAddress(addr), chain.Client) + if err != nil { + return err + } + sCfg, err := onRampC.GetStaticConfig(nil) + if err != nil { + return fmt.Errorf("failed to get static config chain %s: %w", chain.String(), err) + } + mu.Lock() + if state.EVM2EVMOnRamp == nil { + state.EVM2EVMOnRamp = make(map[uint64]*evm_2_evm_onramp.EVM2EVMOnRamp) + } + state.EVM2EVMOnRamp[sCfg.DestChainSelector] = onRampC + state.ABIByAddress[addr] = evm_2_evm_onramp.EVM2EVMOnRampABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.OffRamp, deployment.Version1_5_0).String(), cldf.NewTypeAndVersion(ccipshared.EVM2EVMOffRamp, deployment.Version1_5_0).String(): - if !config.loadLegacyContracts { - continue - } - offRamp, err := evm_2_evm_offramp.NewEVM2EVMOffRamp(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - sCfg, err := offRamp.GetStaticConfig(nil) - if err != nil { - return state, err - } - if state.EVM2EVMOffRamp == nil { - state.EVM2EVMOffRamp = make(map[uint64]*evm_2_evm_offramp.EVM2EVMOffRamp) - } - state.EVM2EVMOffRamp[sCfg.SourceChainSelector] = offRamp - state.ABIByAddress[address] = evm_2_evm_offramp.EVM2EVMOffRampABI + addr := address + work = append(work, func(ctx context.Context) error { + if !config.loadLegacyContracts { + return nil + } + offRamp, err := evm_2_evm_offramp.NewEVM2EVMOffRamp(common.HexToAddress(addr), chain.Client) + if err != nil { + return err + } + sCfg, err := offRamp.GetStaticConfig(nil) + if err != nil { + return err + } + mu.Lock() + if state.EVM2EVMOffRamp == nil { + state.EVM2EVMOffRamp = make(map[uint64]*evm_2_evm_offramp.EVM2EVMOffRamp) + } + state.EVM2EVMOffRamp[sCfg.SourceChainSelector] = offRamp + state.ABIByAddress[addr] = evm_2_evm_offramp.EVM2EVMOffRampABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.CommitStore, deployment.Version1_5_0).String(): - if !config.loadLegacyContracts { - continue - } - commitStore, err := commit_store.NewCommitStore(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - sCfg, err := commitStore.GetStaticConfig(nil) - if err != nil { - return state, err - } - if state.CommitStore == nil { - state.CommitStore = make(map[uint64]*commit_store.CommitStore) - } - state.CommitStore[sCfg.SourceChainSelector] = commitStore - state.ABIByAddress[address] = commit_store.CommitStoreABI + addr := address + work = append(work, func(ctx context.Context) error { + if !config.loadLegacyContracts { + return nil + } + commitStore, err := commit_store.NewCommitStore(common.HexToAddress(addr), chain.Client) + if err != nil { + return err + } + sCfg, err := commitStore.GetStaticConfig(nil) + if err != nil { + return err + } + mu.Lock() + if state.CommitStore == nil { + state.CommitStore = make(map[uint64]*commit_store.CommitStore) + } + state.CommitStore[sCfg.SourceChainSelector] = commitStore + state.ABIByAddress[addr] = commit_store.CommitStoreABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.PriceRegistry, deployment.Version1_2_0).String(): if !config.loadLegacyContracts { continue @@ -1612,43 +1725,61 @@ func LoadChainState(ctx context.Context, chain cldf_evm.Chain, addresses map[str state.BurnMintERC20WithDrip[ccipshared.TokenSymbol(symbol)] = ERC677HelperToken state.ABIByAddress[address] = burn_mint_erc20_with_drip.BurnMintERC20WithDripABI case cldf.NewTypeAndVersion(ccipshared.BurnMintWithExternalMinterTokenPool, deployment.Version1_6_0).String(): - addr := common.HexToAddress(address) - pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_mint_with_external_minter_token_pool.NewBurnMintWithExternalMinterTokenPool, addr, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", addr, err) - } - state.BurnMintWithExternalMinterTokenPool = helpers.AddValueToNestedMap(state.BurnMintWithExternalMinterTokenPool, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = burn_mint_with_external_minter_token_pool.BurnMintWithExternalMinterTokenPoolABI + addr := address + work = append(work, func(ctx context.Context) error { + a := common.HexToAddress(addr) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_mint_with_external_minter_token_pool.NewBurnMintWithExternalMinterTokenPool, a, chain.Client) + if err != nil { + return fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", a, err) + } + mu.Lock() + state.BurnMintWithExternalMinterTokenPool = helpers.AddValueToNestedMap(state.BurnMintWithExternalMinterTokenPool, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[addr] = burn_mint_with_external_minter_token_pool.BurnMintWithExternalMinterTokenPoolABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.HybridWithExternalMinterTokenPool, deployment.Version1_6_0).String(): - addr := common.HexToAddress(address) - pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, hybrid_with_external_minter_token_pool.NewHybridWithExternalMinterTokenPool, addr, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", addr, err) - } - state.HybridWithExternalMinterTokenPool = helpers.AddValueToNestedMap(state.HybridWithExternalMinterTokenPool, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = hybrid_with_external_minter_token_pool.HybridWithExternalMinterTokenPoolABI + addr := address + work = append(work, func(ctx context.Context) error { + a := common.HexToAddress(addr) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, hybrid_with_external_minter_token_pool.NewHybridWithExternalMinterTokenPool, a, chain.Client) + if err != nil { + return fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", a, err) + } + mu.Lock() + state.HybridWithExternalMinterTokenPool = helpers.AddValueToNestedMap(state.HybridWithExternalMinterTokenPool, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[addr] = hybrid_with_external_minter_token_pool.HybridWithExternalMinterTokenPoolABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.TokenGovernor, deployment.Version1_6_0).String(): - tokenGovernor, err := token_governor.NewTokenGovernor(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if state.TokenGovernor == nil { - state.TokenGovernor = make(map[ccipshared.TokenSymbol]*token_governor.TokenGovernor) - } - tokenAddress, err := tokenGovernor.GetToken(&bind.CallOpts{Context: ctx}) - if err != nil { - return state, fmt.Errorf("failed to get token address of token governor at %s: %w", address, err) - } - token, err := erc20.NewERC20(common.HexToAddress(tokenAddress.String()), chain.Client) - if err != nil { - return state, err - } - symbol, err := token.Symbol(&bind.CallOpts{Context: ctx}) - if err != nil { - return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) - } - state.TokenGovernor[ccipshared.TokenSymbol(symbol)] = tokenGovernor - state.ABIByAddress[address] = token_governor.TokenGovernorABI + addr := address + work = append(work, func(ctx context.Context) error { + tokenGovernor, err := token_governor.NewTokenGovernor(common.HexToAddress(addr), chain.Client) + if err != nil { + return err + } + tokenAddress, err := tokenGovernor.GetToken(&bind.CallOpts{Context: ctx}) + if err != nil { + return fmt.Errorf("failed to get token address of token governor at %s: %w", addr, err) + } + token, err := erc20.NewERC20(common.HexToAddress(tokenAddress.String()), chain.Client) + if err != nil { + return err + } + symbol, err := token.Symbol(&bind.CallOpts{Context: ctx}) + if err != nil { + return fmt.Errorf("failed to get token symbol of token at %s: %w", addr, err) + } + mu.Lock() + if state.TokenGovernor == nil { + state.TokenGovernor = make(map[ccipshared.TokenSymbol]*token_governor.TokenGovernor) + } + state.TokenGovernor[ccipshared.TokenSymbol(symbol)] = tokenGovernor + state.ABIByAddress[addr] = token_governor.TokenGovernorABI + mu.Unlock() + return nil + }) case cldf.NewTypeAndVersion(ccipshared.EVMSignerRegistry, deployment.Version1_0_0).String(): signerRegistry, err := signer_registry.NewSignerRegistry(common.HexToAddress(address), chain.Client) if err != nil { @@ -1658,73 +1789,79 @@ func LoadChainState(ctx context.Context, chain cldf_evm.Chain, addresses map[str state.SignerRegistry = signerRegistry state.ABIByAddress[address] = signer_registry.SignerRegistryABI case cldf.NewTypeAndVersion(ccipshared.TransparentUpgradeableProxy, deployment.Version1_6_1).String(): - var ( - symbol string - err error - isPaused bool - ) - standardToken, err := burn_mint_erc20_transparent.NewBurnMintERC20Transparent(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - pausableToken, err := burn_mint_erc20_pausable_freezable_transparent.NewBurnMintERC20PausableFreezableTransparent(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if _, isPausedErr := pausableToken.Paused(&bind.CallOpts{Context: ctx}); isPausedErr == nil { - isPaused = true - symbol, err = pausableToken.Symbol(&bind.CallOpts{Context: ctx}) - } else { - symbol, err = standardToken.Symbol(&bind.CallOpts{Context: ctx}) - } - if err != nil { - return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) - } - transparent, err := transparent_upgradeable_proxy.NewTransparentUpgradeableProxy(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - storageBytes, err := chain.Client.StorageAt(ctx, transparent.Address(), ccipshared.TUPImplementationSlot, nil) - if err != nil { - return state, fmt.Errorf("failed to get storage at slot %s for TransparentUpgradeableProxy at %s for %s token on %s: %w", ccipshared.TUPImplementationSlot, transparent.Address(), symbol, chain, err) - } - erc20Address := common.BytesToAddress(storageBytes) - standardToken, err = burn_mint_erc20_transparent.NewBurnMintERC20Transparent(erc20Address, chain.Client) - if err != nil { - return state, err - } - storageBytes, err = chain.Client.StorageAt(ctx, transparent.Address(), ccipshared.AdminSlot, nil) - if err != nil { - return state, fmt.Errorf("failed to get storage at slot %s for TransparentUpgradeableProxy at %s for %s token on %s: %w", ccipshared.AdminSlot, transparent.Address(), symbol, chain, err) - } - proxyAdmin := common.BytesToAddress(storageBytes) - proxy, err := proxy_admin.NewProxyAdmin(proxyAdmin, chain.Client) - if err != nil { - return state, err - } - if !isPaused && state.BurnMintERC20Transparent == nil { - state.BurnMintERC20Transparent = make(map[ccipshared.TokenSymbol]*burn_mint_erc20_transparent.BurnMintERC20Transparent) - } - if isPaused && state.BurnMintERC20PausableFreezableTransparent == nil { - state.BurnMintERC20PausableFreezableTransparent = make(map[ccipshared.TokenSymbol]*burn_mint_erc20_pausable_freezable_transparent.BurnMintERC20PausableFreezableTransparent) - } - if state.ProxyAdmin == nil { - state.ProxyAdmin = make(map[ccipshared.TokenSymbol]*proxy_admin.ProxyAdmin) - } - if state.TransparentUpgradeableProxy == nil { - state.TransparentUpgradeableProxy = make(map[ccipshared.TokenSymbol]*transparent_upgradeable_proxy.TransparentUpgradeableProxy) - } - if isPaused { - state.BurnMintERC20PausableFreezableTransparent[ccipshared.TokenSymbol(symbol)] = pausableToken - state.ABIByAddress[erc20Address.String()] = burn_mint_erc20_pausable_freezable_transparent.BurnMintERC20PausableFreezableTransparentABI - } else { - state.BurnMintERC20Transparent[ccipshared.TokenSymbol(symbol)] = standardToken - state.ABIByAddress[erc20Address.String()] = burn_mint_erc20_transparent.BurnMintERC20TransparentABI - } - state.ProxyAdmin[ccipshared.TokenSymbol(symbol)] = proxy - state.ABIByAddress[proxyAdmin.String()] = proxy_admin.ProxyAdminABI - state.TransparentUpgradeableProxy[ccipshared.TokenSymbol(symbol)] = transparent - state.ABIByAddress[address] = transparent_upgradeable_proxy.TransparentUpgradeableProxyABI + addr := address + work = append(work, func(ctx context.Context) error { + var ( + symbol string + err error + isPaused bool + ) + standardToken, err := burn_mint_erc20_transparent.NewBurnMintERC20Transparent(common.HexToAddress(addr), chain.Client) + if err != nil { + return err + } + pausableToken, err := burn_mint_erc20_pausable_freezable_transparent.NewBurnMintERC20PausableFreezableTransparent(common.HexToAddress(addr), chain.Client) + if err != nil { + return err + } + if _, isPausedErr := pausableToken.Paused(&bind.CallOpts{Context: ctx}); isPausedErr == nil { + isPaused = true + symbol, err = pausableToken.Symbol(&bind.CallOpts{Context: ctx}) + } else { + symbol, err = standardToken.Symbol(&bind.CallOpts{Context: ctx}) + } + if err != nil { + return fmt.Errorf("failed to get token symbol of token at %s: %w", addr, err) + } + transparent, err := transparent_upgradeable_proxy.NewTransparentUpgradeableProxy(common.HexToAddress(addr), chain.Client) + if err != nil { + return err + } + storageBytes, err := chain.Client.StorageAt(ctx, transparent.Address(), ccipshared.TUPImplementationSlot, nil) + if err != nil { + return fmt.Errorf("failed to get storage at slot %s for TransparentUpgradeableProxy at %s for %s token on %s: %w", ccipshared.TUPImplementationSlot, transparent.Address(), symbol, chain, err) + } + erc20Address := common.BytesToAddress(storageBytes) + standardToken, err = burn_mint_erc20_transparent.NewBurnMintERC20Transparent(erc20Address, chain.Client) + if err != nil { + return err + } + storageBytes, err = chain.Client.StorageAt(ctx, transparent.Address(), ccipshared.AdminSlot, nil) + if err != nil { + return fmt.Errorf("failed to get storage at slot %s for TransparentUpgradeableProxy at %s for %s token on %s: %w", ccipshared.AdminSlot, transparent.Address(), symbol, chain, err) + } + proxyAdmin := common.BytesToAddress(storageBytes) + proxy, err := proxy_admin.NewProxyAdmin(proxyAdmin, chain.Client) + if err != nil { + return err + } + mu.Lock() + if !isPaused && state.BurnMintERC20Transparent == nil { + state.BurnMintERC20Transparent = make(map[ccipshared.TokenSymbol]*burn_mint_erc20_transparent.BurnMintERC20Transparent) + } + if isPaused && state.BurnMintERC20PausableFreezableTransparent == nil { + state.BurnMintERC20PausableFreezableTransparent = make(map[ccipshared.TokenSymbol]*burn_mint_erc20_pausable_freezable_transparent.BurnMintERC20PausableFreezableTransparent) + } + if state.ProxyAdmin == nil { + state.ProxyAdmin = make(map[ccipshared.TokenSymbol]*proxy_admin.ProxyAdmin) + } + if state.TransparentUpgradeableProxy == nil { + state.TransparentUpgradeableProxy = make(map[ccipshared.TokenSymbol]*transparent_upgradeable_proxy.TransparentUpgradeableProxy) + } + if isPaused { + state.BurnMintERC20PausableFreezableTransparent[ccipshared.TokenSymbol(symbol)] = pausableToken + state.ABIByAddress[erc20Address.String()] = burn_mint_erc20_pausable_freezable_transparent.BurnMintERC20PausableFreezableTransparentABI + } else { + state.BurnMintERC20Transparent[ccipshared.TokenSymbol(symbol)] = standardToken + state.ABIByAddress[erc20Address.String()] = burn_mint_erc20_transparent.BurnMintERC20TransparentABI + } + state.ProxyAdmin[ccipshared.TokenSymbol(symbol)] = proxy + state.ABIByAddress[proxyAdmin.String()] = proxy_admin.ProxyAdminABI + state.TransparentUpgradeableProxy[ccipshared.TokenSymbol(symbol)] = transparent + state.ABIByAddress[addr] = transparent_upgradeable_proxy.TransparentUpgradeableProxyABI + mu.Unlock() + return nil + }) default: // ManyChainMultiSig 1.0.0 can have any of these labels, it can have either 1,2 or 3 of these - // bypasser, proposer and canceller @@ -1767,6 +1904,15 @@ func LoadChainState(ctx context.Context, chain cldf_evm.Chain, addresses map[str return state, fmt.Errorf("unknown contract %s", tvStr) } } + // run RPC-bound work in parallel + grp, gctx := errgroup.WithContext(ctx) + grp.SetLimit(10) + for _, w := range work { + grp.Go(func() error { return w(gctx) }) + } + if err := grp.Wait(); err != nil { + return state, err + } return state, nil }